From e03ac9f0c3f5f2e79c41fd02d9b90831dfd78a2e Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Tue, 8 Dec 2015 13:27:02 -0500 Subject: mips: Fix CPC_BASE_ADDR mask to match datasheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to 'MIPS32® interAptivTM Multiprocessing System Programmer’s Guide' CPC_BASE_ADDR takes bits [31:15]. This change is tested ith mt7621 which wasn't working without it. Signed-off-by: Nikolay Martynov Reviewed-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11766/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index d4635391c36a..4ac8e4b69fb5 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -290,8 +290,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_GIC_BASE_GICEN_MSK (_ULCAST_(0x1) << 0) /* GCR_CPC_BASE register fields */ -#define CM_GCR_CPC_BASE_CPCBASE_SHF 17 -#define CM_GCR_CPC_BASE_CPCBASE_MSK (_ULCAST_(0x7fff) << 17) +#define CM_GCR_CPC_BASE_CPCBASE_SHF 15 +#define CM_GCR_CPC_BASE_CPCBASE_MSK (_ULCAST_(0x1ffff) << 15) #define CM_GCR_CPC_BASE_CPCEN_SHF 0 #define CM_GCR_CPC_BASE_CPCEN_MSK (_ULCAST_(0x1) << 0) -- cgit v1.2.3-59-g8ed1b From c80e1b62ffca52e2d1d865ee58bc79c4c0c55005 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 11 Apr 2016 09:10:19 -0500 Subject: MIPS: Fix crash registers on non-crashing CPUs As part of handling a crash on an SMP system, an IPI is send to all other CPUs to save their current registers and stop. It was using task_pt_regs(current) to get the registers, but that will only be accurate if the CPU was interrupted running in userland. Instead allow the architecture to pass in the registers (all pass NULL now, but allow for the future) and then use get_irq_regs() which should be accurate as we are in an interrupt. Fall back to task_pt_regs(current) if nothing else is available. Signed-off-by: Corey Minyard Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13050/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/crash.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c index d434d5d5ae6e..610f0f3bdb34 100644 --- a/arch/mips/kernel/crash.c +++ b/arch/mips/kernel/crash.c @@ -14,12 +14,22 @@ static int crashing_cpu = -1; static cpumask_t cpus_in_crash = CPU_MASK_NONE; #ifdef CONFIG_SMP -static void crash_shutdown_secondary(void *ignore) +static void crash_shutdown_secondary(void *passed_regs) { - struct pt_regs *regs; + struct pt_regs *regs = passed_regs; int cpu = smp_processor_id(); - regs = task_pt_regs(current); + /* + * If we are passed registers, use those. Otherwise get the + * regs from the last interrupt, which should be correct, as + * we are in an interrupt. But if the regs are not there, + * pull them from the top of the stack. They are probably + * wrong, but we need something to keep from crashing again. + */ + if (!regs) + regs = get_irq_regs(); + if (!regs) + regs = task_pt_regs(current); if (!cpu_online(cpu)) return; -- cgit v1.2.3-59-g8ed1b From 5daebc477da4dfeb31ae193d83084def58fd2697 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 8 Feb 2016 18:43:49 +0000 Subject: MIPS: Fix siginfo.h to use strict posix types Commit 85efde6f4e0d ("make exported headers use strict posix types") changed the asm-generic siginfo.h to use the __kernel_* types, and commit 3a471cbc081b ("remove __KERNEL_STRICT_NAMES") make the internal types accessible only to the kernel, but the MIPS implementation hasn't been updated to match. Switch to proper types now so that the exported asm/siginfo.h won't produce quite so many compiler errors when included alone by a user program. Signed-off-by: James Hogan Cc: Christopher Ferris Cc: linux-mips@linux-mips.org Cc: # 2.6.30- Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12477/ Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/siginfo.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index cc49dc240d67..9db5bda8df3f 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -42,13 +42,13 @@ typedef struct siginfo { /* kill() */ struct { - pid_t _pid; /* sender's pid */ + __kernel_pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ } _kill; /* POSIX.1b timers */ struct { - timer_t _tid; /* timer id */ + __kernel_timer_t _tid; /* timer id */ int _overrun; /* overrun count */ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; sigval_t _sigval; /* same as below */ @@ -57,26 +57,26 @@ typedef struct siginfo { /* POSIX.1b signals */ struct { - pid_t _pid; /* sender's pid */ + __kernel_pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ sigval_t _sigval; } _rt; /* SIGCHLD */ struct { - pid_t _pid; /* which child */ + __kernel_pid_t _pid; /* which child */ __ARCH_SI_UID_T _uid; /* sender's uid */ int _status; /* exit code */ - clock_t _utime; - clock_t _stime; + __kernel_clock_t _utime; + __kernel_clock_t _stime; } _sigchld; /* IRIX SIGCHLD */ struct { - pid_t _pid; /* which child */ - clock_t _utime; + __kernel_pid_t _pid; /* which child */ + __kernel_clock_t _utime; int _status; /* exit code */ - clock_t _stime; + __kernel_clock_t _stime; } _irix_sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ -- cgit v1.2.3-59-g8ed1b From 578bffc82ec5332d97860ac529f90b0bcfaf8b5f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 4 Apr 2016 10:04:52 +0100 Subject: MIPS: Don't BUG_ON when no IPI domain is found Commit fbde2d7d8290 ("MIPS: Add generic SMP IPI support") introduced code that BUG_ON's in the case of a kernel that supports IPI domains but does not have one at runtime. This case is possible on Malta where for IPIs we may use either the GIC (which has an IPI IRQ domain implementation) or core-local software interrupts between VPEs (which do not currently have an IPI IRQ domain implementation). We can not know which will be used until runtime when we know whether a GIC is actually present, and if we run on a system with multiple VPEs and no GIC then the BUG_ON is hit. Commit 19fb5818ed60 ("IPS: Fix broken malta qemu") worked around this for the single-core single-VPE case typically seen using QEMU, but does not catch the multi-VPE case. This patch removes the insufficient CPU presence check that was added and works around the bug differently, effectively reverting that commit. A simple way to reproduce this bug is by using QEMU, which partially implements the MT ASE but does not implement the GIC as of version 2.5. Using "-cpu 34Kf -smp 2" will present a system with 2 VPEs in one core & no GIC, hitting the BUG_ON. Given that we're post-merge-window on the way to v4.6, avoid this by just returning from mips_smp_ipi_init when no IPI IRQ domain is found. Ideally at some point all IPI implementations would be converted to the same IPI IRQ domain interface & we'd be able to restore the check. Signed-off-by: Paul Burton Cc: Qais Yousef Fixes: fbde2d7d8290 ("MIPS: Add generic SMP IPI support") Fixes: 19fb5818ed60 ("IPS: Fix broken malta qemu") Reverts: 19fb5818ed60 ("IPS: Fix broken malta qemu") Cc: Qais Yousef Cc: James Hogan Cc: Alex Smith Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13007/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 27cb638f0824..f9d01e953acb 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -243,18 +243,6 @@ static int __init mips_smp_ipi_init(void) struct irq_domain *ipidomain; struct device_node *node; - /* - * In some cases like qemu-malta, it is desired to try SMP with - * a single core. Qemu-malta has no GIC, so an attempt to set any IPIs - * would cause a BUG_ON() to be triggered since there's no ipidomain. - * - * Since for a single core system IPIs aren't required really, skip the - * initialisation which should generally keep any such configurations - * happy and only fail hard when trying to truely run SMP. - */ - if (cpumask_weight(cpu_possible_mask) == 1) - return 0; - node = of_irq_find_parent(of_root); ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI); @@ -266,7 +254,17 @@ static int __init mips_smp_ipi_init(void) if (node && !ipidomain) ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI); - BUG_ON(!ipidomain); + /* + * There are systems which only use IPI domains some of the time, + * depending upon configuration we don't know until runtime. An + * example is Malta where we may compile in support for GIC & the + * MT ASE, but run on a system which has multiple VPEs in a single + * core and doesn't include a GIC. Until all IPI implementations + * have been converted to use IPI domains the best we can do here + * is to return & hope some other code sets up the IPIs. + */ + if (!ipidomain) + return 0; call_virq = irq_reserve_ipi(ipidomain, cpu_possible_mask); BUG_ON(!call_virq); -- cgit v1.2.3-59-g8ed1b From cbbda6e7c9c3e4532bd70a73ff9d5e6655c894dc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 29 Jan 2016 21:17:26 -0800 Subject: MIPS: BMIPS: Fix PRID_IMP_BMIPS5000 masking for BMIPS5200 BMIPS5000 have a PrID value of 0x5A00 and BMIPS5200 have a PrID value of 0x5B00, which, masked with 0x5A00, returns 0x5A00. Update all conditionals on the PrID to cover both variants since we are going to need this to enable BMIPS5200 SMP. The existing check, masking with 0xFF00 would not cover BMIPS5200 at all. Fixes: 68e6a78373a6d ("MIPS: BMIPS: Add PRId for BMIPS5200 (Whirlwind)") Fixes: 6465460c92a85 ("MIPS: BMIPS: change compile time checks to runtime checks") Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Cc: jaedon.shin@gmail.com Cc: jfraser@broadcom.com Cc: pgynther@google.com Cc: dragan.stancevic@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12279/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/bmips_vec.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S index 86495072a922..d9495f3f3fad 100644 --- a/arch/mips/kernel/bmips_vec.S +++ b/arch/mips/kernel/bmips_vec.S @@ -93,7 +93,8 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp) #if defined(CONFIG_CPU_BMIPS5000) mfc0 k0, CP0_PRID li k1, PRID_IMP_BMIPS5000 - andi k0, 0xff00 + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ + andi k0, PRID_IMP_BMIPS5000 bne k0, k1, 1f /* if we're not on core 0, this must be the SMP boot signal */ @@ -166,10 +167,12 @@ bmips_smp_entry: 2: #endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */ #if defined(CONFIG_CPU_BMIPS5000) - /* set exception vector base */ + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ li k1, PRID_IMP_BMIPS5000 + andi k0, PRID_IMP_BMIPS5000 bne k0, k1, 3f + /* set exception vector base */ la k0, ebase lw k0, 0(k0) mtc0 k0, $15, 1 @@ -263,6 +266,8 @@ LEAF(bmips_enable_xks01) #endif /* CONFIG_CPU_BMIPS4380 */ #if defined(CONFIG_CPU_BMIPS5000) li t1, PRID_IMP_BMIPS5000 + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ + andi t2, PRID_IMP_BMIPS5000 bne t2, t1, 2f mfc0 t0, $22, 5 -- cgit v1.2.3-59-g8ed1b From 21b30c00f3067001519eda166675c1958b163c91 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Feb 2016 18:14:50 -0800 Subject: MIPS: BMIPS: Add Whirlwind (BMIPS5200) initialization code Import bmips_5xxx_init.S from the stblinux-3.3 tree, and to make sure that this would work nicely with a BMIPS multiplatform kernel (with BMIPS330, BMIPS43XX and BMIPS5000 enabled), update soft_reset to check for the BMIPS5200 processor id (PRID_IMP_BMIPS5200) and execute bmips_5xxx_init for these processors to bring them online. Tested on 7425, 7429 and 7435 with CPU hotplug. 7435 SMP still needs some additional changes in the L1 interrupt area to work properly with interrupt affinity. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: jaedon.shin@gmail.com Cc: dragan.stancevic@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/12377/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/bmips_5xxx_init.S | 753 +++++++++++++++++++++++++++++++++++++ arch/mips/kernel/bmips_vec.S | 41 +- 3 files changed, 792 insertions(+), 4 deletions(-) create mode 100644 arch/mips/kernel/bmips_5xxx_init.S (limited to 'arch') diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index b0988fd62fcc..8a8b775fa7c8 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP_UP) += smp-up.o -obj-$(CONFIG_CPU_BMIPS) += smp-bmips.o bmips_vec.o +obj-$(CONFIG_CPU_BMIPS) += smp-bmips.o bmips_vec.o bmips_5xxx_init.o obj-$(CONFIG_MIPS_MT) += mips-mt.o obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o diff --git a/arch/mips/kernel/bmips_5xxx_init.S b/arch/mips/kernel/bmips_5xxx_init.S new file mode 100644 index 000000000000..788ebf9a365d --- /dev/null +++ b/arch/mips/kernel/bmips_5xxx_init.S @@ -0,0 +1,753 @@ + +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2011-2012 by Broadcom Corporation + * + * Init for bmips 5000. + * Used to init second core in dual core 5000's. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CPU_BMIPS5000 + + +#define cacheop(kva, size, linesize, op) \ + .set noreorder ; \ + addu t1, kva, size ; \ + subu t2, linesize, 1 ; \ + not t2 ; \ + and t0, kva, t2 ; \ + addiu t1, t1, -1 ; \ + and t1, t2 ; \ +9: cache op, 0(t0) ; \ + bne t0, t1, 9b ; \ + addu t0, linesize ; \ + .set reorder ; + + + +#define IS_SHIFT 22 +#define IL_SHIFT 19 +#define IA_SHIFT 16 +#define DS_SHIFT 13 +#define DL_SHIFT 10 +#define DA_SHIFT 7 +#define IS_MASK 7 +#define IL_MASK 7 +#define IA_MASK 7 +#define DS_MASK 7 +#define DL_MASK 7 +#define DA_MASK 7 +#define ICE_MASK 0x80000000 +#define DCE_MASK 0x40000000 + +#define CP0_BRCM_CONFIG0 $22, 0 +#define CP0_BRCM_MODE $22, 1 +#define CP0_CONFIG_K0_MASK 7 + +#define CP0_ICACHE_TAG_LO $28 +#define CP0_ICACHE_DATA_LO $28, 1 +#define CP0_DCACHE_TAG_LO $28, 2 +#define CP0_D_SEC_CACHE_DATA_LO $28, 3 +#define CP0_ICACHE_TAG_HI $29 +#define CP0_ICACHE_DATA_HI $29, 1 +#define CP0_DCACHE_TAG_HI $29, 2 + +#define CP0_BRCM_MODE_Luc_MASK (1 << 11) +#define CP0_BRCM_CONFIG0_CWF_MASK (1 << 20) +#define CP0_BRCM_CONFIG0_TSE_MASK (1 << 19) +#define CP0_BRCM_MODE_SET_MASK (1 << 7) +#define CP0_BRCM_MODE_ClkRATIO_MASK (7 << 4) +#define CP0_BRCM_MODE_BrPRED_MASK (3 << 24) +#define CP0_BRCM_MODE_BrPRED_SHIFT 24 +#define CP0_BRCM_MODE_BrHIST_MASK (0x1f << 20) +#define CP0_BRCM_MODE_BrHIST_SHIFT 20 + +/* ZSC L2 Cache Register Access Register Definitions */ +#define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 24 + +#define BRCM_ZSC_CONFIG_REG 0 << 3 +#define BRCM_ZSC_REQ_BUFFER_REG 2 << 3 +#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0 4 << 3 +#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1 6 << 3 +#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2 8 << 3 + +#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0 0xa << 3 +#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1 0xc << 3 + +#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0 0xe << 3 +#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1 0x10 << 3 + +#define BRCM_ZSC_CONFIG_LMB1En 1 << (15) +#define BRCM_ZSC_CONFIG_LMB0En 1 << (14) + +/* branch predition values */ + +#define BRCM_BrPRED_ALL_TAKEN (0x0) +#define BRCM_BrPRED_ALL_NOT_TAKEN (0x1) +#define BRCM_BrPRED_BHT_ENABLE (0x2) +#define BRCM_BrPRED_PREDICT_BACKWARD (0x3) + + + +.align 2 +/* + * Function: size_i_cache + * Arguments: None + * Returns: v0 = i cache size, v1 = I cache line size + * Description: compute the I-cache size and I-cache line size + * Trashes: v0, v1, a0, t0 + * + * pseudo code: + * + */ + +LEAF(size_i_cache) + .set noreorder + + mfc0 a0, CP0_CONFIG, 1 + move t0, a0 + + /* + * Determine sets per way: IS + * + * This field contains the number of sets (i.e., indices) per way of + * the instruction cache: + * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k + * vi) 0x5 - 0x7: Reserved. + */ + + srl a0, a0, IS_SHIFT + and a0, a0, IS_MASK + + /* sets per way = (64< Date: Wed, 13 Apr 2016 01:17:57 +0200 Subject: MIPS: BMIPS: Make whitespacely correct. Signed-off-by: Ralf Baechle --- arch/mips/kernel/bmips_5xxx_init.S | 272 ++++++++++++++++++------------------- 1 file changed, 136 insertions(+), 136 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/bmips_5xxx_init.S b/arch/mips/kernel/bmips_5xxx_init.S index 788ebf9a365d..adaa82e00f2b 100644 --- a/arch/mips/kernel/bmips_5xxx_init.S +++ b/arch/mips/kernel/bmips_5xxx_init.S @@ -27,16 +27,16 @@ #define cacheop(kva, size, linesize, op) \ .set noreorder ; \ - addu t1, kva, size ; \ - subu t2, linesize, 1 ; \ - not t2 ; \ - and t0, kva, t2 ; \ - addiu t1, t1, -1 ; \ - and t1, t2 ; \ -9: cache op, 0(t0) ; \ - bne t0, t1, 9b ; \ - addu t0, linesize ; \ - .set reorder ; + addu t1, kva, size ; \ + subu t2, linesize, 1 ; \ + not t2 ; \ + and t0, kva, t2 ; \ + addiu t1, t1, -1 ; \ + and t1, t2 ; \ +9: cache op, 0(t0) ; \ + bne t0, t1, 9b ; \ + addu t0, linesize ; \ + .set reorder ; @@ -59,13 +59,13 @@ #define CP0_BRCM_MODE $22, 1 #define CP0_CONFIG_K0_MASK 7 -#define CP0_ICACHE_TAG_LO $28 -#define CP0_ICACHE_DATA_LO $28, 1 -#define CP0_DCACHE_TAG_LO $28, 2 +#define CP0_ICACHE_TAG_LO $28 +#define CP0_ICACHE_DATA_LO $28, 1 +#define CP0_DCACHE_TAG_LO $28, 2 #define CP0_D_SEC_CACHE_DATA_LO $28, 3 -#define CP0_ICACHE_TAG_HI $29 -#define CP0_ICACHE_DATA_HI $29, 1 -#define CP0_DCACHE_TAG_HI $29, 2 +#define CP0_ICACHE_TAG_HI $29 +#define CP0_ICACHE_DATA_HI $29, 1 +#define CP0_DCACHE_TAG_HI $29, 2 #define CP0_BRCM_MODE_Luc_MASK (1 << 11) #define CP0_BRCM_CONFIG0_CWF_MASK (1 << 20) @@ -78,7 +78,7 @@ #define CP0_BRCM_MODE_BrHIST_SHIFT 20 /* ZSC L2 Cache Register Access Register Definitions */ -#define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 24 +#define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 24 #define BRCM_ZSC_CONFIG_REG 0 << 3 #define BRCM_ZSC_REQ_BUFFER_REG 2 << 3 @@ -117,9 +117,9 @@ */ LEAF(size_i_cache) - .set noreorder + .set noreorder - mfc0 a0, CP0_CONFIG, 1 + mfc0 a0, CP0_CONFIG, 1 move t0, a0 /* @@ -131,13 +131,13 @@ LEAF(size_i_cache) * vi) 0x5 - 0x7: Reserved. */ - srl a0, a0, IS_SHIFT - and a0, a0, IS_MASK + srl a0, a0, IS_SHIFT + and a0, a0, IS_MASK /* sets per way = (64< Date: Wed, 3 Feb 2016 18:14:51 -0800 Subject: MIPS: BMIPS: Add missing 7038 L1 register cells to BCM7435 7435 has 4 7038 L1 base register address for each of its Core + TP (for a total of 4 threads of execution), add the two missing cells for Core 1. We are providing HW interrupts 2/3 even for Core 1/TP0/TP1 because that's what they are, and we can later decide to remap these in software to provide proper interrupt affinity/parenting. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: jaedon.shin@gmail.com Cc: dragan.stancevic@gmail.com Cc: jogo@openwrt.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12378/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7435.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index 56035e5b7008..a1757efe612f 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -63,13 +63,14 @@ periph_intc: periph_intc@41b500 { compatible = "brcm,bcm7038-l1-intc"; - reg = <0x41b500 0x40>, <0x41b600 0x40>; + reg = <0x41b500 0x40>, <0x41b600 0x40>, + <0x41b700 0x40>, <0x41b800 0x40>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&cpu_intc>; - interrupts = <2>, <3>; + interrupts = <2>, <3>, <2>, <3>; }; sun_l2_intc: sun_l2_intc@403000 { -- cgit v1.2.3-59-g8ed1b From 904c3b4952fff6d9d7a5e26b27d4a194b8f538d4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Feb 2016 18:14:52 -0800 Subject: MIPS: BMIPS: Remove maxcpus from BCM97435SVMB DTS Now that SMP properly works on 7435, do not restrict the number of core, unleash them all. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: jaedon.shin@gmail.com Cc: dragan.stancevic@gmail.com Cc: jogo@openwrt.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12379/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm97435svmb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm97435svmb.dts b/arch/mips/boot/dts/brcm/bcm97435svmb.dts index 1df088183523..68f486eba3f7 100644 --- a/arch/mips/boot/dts/brcm/bcm97435svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97435svmb.dts @@ -14,7 +14,7 @@ }; chosen { - bootargs = "console=ttyS0,115200 maxcpus=1"; + bootargs = "console=ttyS0,115200"; stdout-path = &uart0; }; }; -- cgit v1.2.3-59-g8ed1b From f6cc0ee98b230b085e019f0c791af68a4f99e446 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Feb 2016 18:14:53 -0800 Subject: MIPS: BMIPS: Fill in current_cpu_data.core Read the core ID in bmips_smp_finish() for BMIPS5000 CPUs to get appropriate processor parenting in set_cpu_sibling_map(). Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: jaedon.shin@gmail.com Cc: dragan.stancevic@gmail.com Cc: jogo@openwrt.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12380/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-bmips.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 78cf8c2f1de0..6d11788b4502 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -243,6 +243,7 @@ static void bmips_init_secondary(void) break; case CPU_BMIPS5000: write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); + current_cpu_data.core = (read_c0_brcm_config() >> 25) & 3; break; } } -- cgit v1.2.3-59-g8ed1b From a816b306c62195b7c43c92cb13330821a96bdc27 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 4 Dec 2015 22:25:01 +0000 Subject: MIPS: Don't unwind to user mode with EVA When unwinding through IRQs and exceptions, the unwinding only continues if the PC is a kernel text address, however since EVA it is possible for user and kernel address ranges to overlap, potentially allowing unwinding to continue to user mode if the user PC happens to be in the kernel text address range. Adjust the check to also ensure that the register state from before the exception is actually running in kernel mode, i.e. !user_mode(regs). I don't believe any harm can come of this problem, since the PC is only output, the stack pointer is checked to ensure it resides within the task's stack page before it is dereferenced in search of the return address, and the return address register is similarly only output (if the PC is in a leaf function or the beginning of a non-leaf function). However unwind_stack() is only meant for unwinding kernel code, so to be correct the unwind should stop there. Signed-off-by: James Hogan Reviewed-by: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # 3.15+ Patchwork: https://patchwork.linux-mips.org/patch/11700/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 92880cee449e..3f5aa3bc191e 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -455,7 +455,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) { regs = (struct pt_regs *)*sp; pc = regs->cp0_epc; - if (__kernel_text_address(pc)) { + if (!user_mode(regs) && __kernel_text_address(pc)) { *sp = regs->regs[29]; *ra = regs->regs[31]; return pc; -- cgit v1.2.3-59-g8ed1b From 81a76d7119f63c359750e4adeff922a31ad1135f Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 4 Dec 2015 22:25:02 +0000 Subject: MIPS: Avoid using unwind_stack() with usermode When showing backtraces in response to traps, for example crashes and address errors (usually unaligned accesses) when they are set in debugfs to be reported, unwind_stack will be used if the PC was in the kernel text address range. However since EVA it is possible for user and kernel address ranges to overlap, and even without EVA userland can still trigger an address error by jumping to a KSeg0 address. Adjust the check to also ensure that it was running in kernel mode. I don't believe any harm can come of this problem, since unwind_stack() is sufficiently defensive, however it is only meant for unwinding kernel code, so to be correct it should use the raw backtracing instead. Signed-off-by: James Hogan Reviewed-by: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # 3.15+ Patchwork: https://patchwork.linux-mips.org/patch/11701/ Signed-off-by: Ralf Baechle (cherry picked from commit d2941a975ac745c607dfb590e92bb30bc352dad9) --- arch/mips/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index ae0c89d23ad7..3cbd98729ab1 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -145,7 +145,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) if (!task) task = current; - if (raw_show_trace || !__kernel_text_address(pc)) { + if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) { show_raw_backtrace(sp); return; } -- cgit v1.2.3-59-g8ed1b From a7e89326b415b5d81c4b1016fd4a40db861eb58d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:36 +0000 Subject: MIPS: Fix watchpoint restoration Commit f51246efee2b ("MIPS: Get rid of finish_arch_switch().") moved the __restore_watch() call from finish_arch_switch() (i.e. after resume() returns) to before the resume() call in switch_to(). This results in watchpoints only being restored when a task is descheduled, preventing the watchpoints from being effective most of the time, except due to chance before the watchpoints are lazily removed. Fix the call sequence from switch_to() through to mips_install_watch_registers() to pass the task_struct pointer of the next task, instead of using current. This allows the watchpoints for the next (non-current) task to be restored without reintroducing finish_arch_switch(). Fixes: f51246efee2b ("MIPS: Get rid of finish_arch_switch().") Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.3.x- Patchwork: https://patchwork.linux-mips.org/patch/12726/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/switch_to.h | 2 +- arch/mips/include/asm/watch.h | 10 +++++----- arch/mips/kernel/pm.c | 2 +- arch/mips/kernel/watch.c | 5 ++--- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index 28b5d84a5022..ebb5c0f2f90d 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -105,7 +105,7 @@ do { \ __clear_software_ll_bit(); \ if (cpu_has_userlocal) \ write_c0_userlocal(task_thread_info(next)->tp_value); \ - __restore_watch(); \ + __restore_watch(next); \ (last) = resume(prev, next, task_thread_info(next)); \ } while (0) diff --git a/arch/mips/include/asm/watch.h b/arch/mips/include/asm/watch.h index 20126ec79359..6ffe3eadf105 100644 --- a/arch/mips/include/asm/watch.h +++ b/arch/mips/include/asm/watch.h @@ -12,21 +12,21 @@ #include -void mips_install_watch_registers(void); +void mips_install_watch_registers(struct task_struct *t); void mips_read_watch_registers(void); void mips_clear_watch_registers(void); void mips_probe_watch_registers(struct cpuinfo_mips *c); #ifdef CONFIG_HARDWARE_WATCHPOINTS -#define __restore_watch() do { \ +#define __restore_watch(task) do { \ if (unlikely(test_bit(TIF_LOAD_WATCH, \ - ¤t_thread_info()->flags))) { \ - mips_install_watch_registers(); \ + &task_thread_info(task)->flags))) { \ + mips_install_watch_registers(task); \ } \ } while (0) #else -#define __restore_watch() do {} while (0) +#define __restore_watch(task) do {} while (0) #endif #endif /* _ASM_WATCH_H */ diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c index fefdf39d3df3..dc814892133c 100644 --- a/arch/mips/kernel/pm.c +++ b/arch/mips/kernel/pm.c @@ -56,7 +56,7 @@ static void mips_cpu_restore(void) write_c0_userlocal(current_thread_info()->tp_value); /* Restore watch registers */ - __restore_watch(); + __restore_watch(current); } /** diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index 2a03abb5bd2c..9b78e375118e 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -15,10 +15,9 @@ * Install the watch registers for the current thread. A maximum of * four registers are installed although the machine may have more. */ -void mips_install_watch_registers(void) +void mips_install_watch_registers(struct task_struct *t) { - struct mips3264_watch_reg_state *watches = - ¤t->thread.watch.mips3264; + struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; switch (current_cpu_data.watch_reg_use_cnt) { default: BUG(); -- cgit v1.2.3-59-g8ed1b From 679eb63779dffbd1fc40d4c218a4ff7c04508a48 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:37 +0000 Subject: MIPS: Enable ptrace hw watchpoints on MIPS R6 HARDWARE_WATCHPOINTS isn't being enabled for CPU_MIPSR6, even though it has an identical hardware watchpoint interface to CPU_MIPSR2, which prevents ptrace watchpoints from being loaded when executing a ptraced process even though the watchpoints are described in /proc/cpuinfo. Enable HARDWARE_WATCHPOINTS for CPU_MIPSR6 too. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12727/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2018c2b0e078..04c5e9c28fba 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1999,7 +1999,7 @@ config MIPS_PGD_C0_CONTEXT # config HARDWARE_WATCHPOINTS bool - default y if CPU_MIPSR1 || CPU_MIPSR2 + default y if CPU_MIPSR1 || CPU_MIPSR2 || CPU_MIPSR6 menu "Kernel type" -- cgit v1.2.3-59-g8ed1b From b2a3c5be4d6df3b04781f430c2201cbbc9900f66 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 22 Jan 2016 10:58:25 +0000 Subject: MIPS: c-r4k: Sync icache when it fills from dcache It is still necessary to handle icache coherency in flush_cache_range() and copy_to_user_page() when the icache fills from the dcache, even though the dcache does not need to be written back. However when this handling was added in commit 2eaa7ec286db ("[MIPS] Handle I-cache coherency in flush_cache_range()"), it did not do any icache flushing when it fills from dcache. Therefore fix r4k_flush_cache_range() to run local_r4k_flush_cache_range() without taking into account whether icache fills from dcache, so that the icache coherency gets handled. Checks are also added in local_r4k_flush_cache_range() so that the dcache blast doesn't take place when icache fills from dcache. A test to mmap a page PROT_READ|PROT_WRITE, modify code in it, and mprotect it to VM_READ|VM_EXEC (similar to case described in above commit) can hit this case quite easily to verify the fix. A similar check was added in commit f8829caee311 ("[MIPS] Fix aliasing bug in copy_to_user_page / copy_from_user_page"), so also fix copy_to_user_page() similarly, to call flush_cache_page() without taking into account whether icache fills from dcache, since flush_cache_page() already takes that into account to avoid performing a dcache flush. Signed-off-by: James Hogan Cc: Leonid Yegoshin Cc: Manuel Lauss Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12179/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 11 +++++++++-- arch/mips/mm/init.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index caac3d747a90..fc7289dfaf5a 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -492,7 +492,14 @@ static inline void local_r4k_flush_cache_range(void * args) if (!(has_valid_asid(vma->vm_mm))) return; - r4k_blast_dcache(); + /* + * If dcache can alias, we must blast it since mapping is changing. + * If executable, we must ensure any dirty lines are written back far + * enough to be visible to icache. + */ + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache(); + /* If executable, blast stale lines from icache */ if (exec) r4k_blast_icache(); } @@ -502,7 +509,7 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma, { int exec = vma->vm_flags & VM_EXEC; - if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + if (cpu_has_dc_aliases || exec) r4k_on_each_cpu(local_r4k_flush_cache_range, vma); } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 7e5fa0938c21..6c6a843b0d17 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -196,7 +196,7 @@ void copy_to_user_page(struct vm_area_struct *vma, if (cpu_has_dc_aliases) SetPageDcacheDirty(page); } - if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) + if (vma->vm_flags & VM_EXEC) flush_cache_page(vma, vaddr, page_to_pfn(page)); } -- cgit v1.2.3-59-g8ed1b From 47f2ac5058a19cbbe70bbccba13d104c60b35bff Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 22 Jan 2016 10:58:26 +0000 Subject: MIPS: I6400: Icache fills from dcache Coherence Manager 3 (CM3) as present in I6400 can fill icache lines effectively from dirty dcaches, so there is no need to flush dirty lines from dcaches through to L2 prior to icache invalidation. Set the MIPS_CACHE_IC_F_DC flag such that cpu_has_ic_fills_f_dc evaluates to true, which avoids those dcache flushes. Signed-off-by: James Hogan Cc: Leonid Yegoshin Cc: Manuel Lauss Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12180/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index fc7289dfaf5a..69e7e5873af3 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1311,6 +1311,7 @@ static void probe_pcache(void) break; case CPU_ALCHEMY: + case CPU_I6400: c->icache.flags |= MIPS_CACHE_IC_F_DC; break; -- cgit v1.2.3-59-g8ed1b From 54292850e8f56c8408db44ea3a5167a0f7c156d5 Mon Sep 17 00:00:00 2001 From: Andreas Ruprecht Date: Thu, 16 Jul 2015 17:52:11 +0200 Subject: MIPS: Sibyte: Fix Kconfig dependencies of SIBYTE_BUS_WATCHER Commit 6793f55cbc84 ("MIPS: sibyte: Amend dependencies for SIBYTE_BUS_WATCHER") changed the dependencies for SIBYTE_BUS_WATCHER to make it visible only if SIBYTE_BCM112X or SIBYTE_SB1250 are enabled. In the code in arch/mips/sibyte/common/bus_watcher, however, a #if defined() check suggests that this functionality should also be available for SIBYTE_BCM1x55 and SIBYTE_BCM1x80. Make it selectable by extending the dependencies of SIBYTE_BUS_WATCHER in arch/mips/sibyte/Kconfig. Reported-by: Jonas Rabenstein Signed-off-by: Andreas Ruprecht Cc: valentinrothberg@gmail.com Cc: stefan.hengelein@fau.de Cc: pebolle@tiscali.nl Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/10736/ Signed-off-by: Ralf Baechle --- arch/mips/sibyte/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index cb9a095f5c5e..707b88441567 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig @@ -143,7 +143,8 @@ config SIBYTE_CFE_CONSOLE config SIBYTE_BUS_WATCHER bool "Support for Bus Watcher statistics" depends on SIBYTE_SB1xxx_SOC && \ - (SIBYTE_BCM112X || SIBYTE_SB1250) + (SIBYTE_BCM112X || SIBYTE_SB1250 || \ + SIBYTE_BCM1x55 || SIBYTE_BCM1x80) help Handle and keep statistics on the bus error interrupts (COR_ECC, BAD_ECC, IO_BUS). -- cgit v1.2.3-59-g8ed1b From a95d069204e178f18476f5499abab0d0d9cbc32c Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 17 Mar 2016 20:37:10 +0800 Subject: MIPS: Reserve nosave data for hibernation After commit 92923ca3aacef63c92d ("mm: meminit: only set page reserved in the memblock region"), the MIPS hibernation is broken. Because pages in nosave data section should be "reserved", but currently they aren't set to "reserved" at initialization. This patch makes hibernation work again. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12888/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 4f607341a793..d20caacfdbd3 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -706,6 +706,9 @@ static void __init arch_mem_init(char **cmdline_p) for_each_memblock(reserved, reg) if (reg->size != 0) reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); + + reserve_bootmem_region(__pa_symbol(&__nosave_begin), + __pa_symbol(&__nosave_end)); /* Reserve for hibernation */ } static void __init resource_init(void) -- cgit v1.2.3-59-g8ed1b From 3484de7bcbed20ecbf2b8d80671619e7059e2dd7 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 17 Mar 2016 20:41:05 +0800 Subject: MIPS: Loongson-3: Reserve 32MB for RS780E integrated GPU Due to datasheet, reserving 0xff800000~0xffffffff (8MB below 4GB) is not enough for RS780E integrated GPU's TOM (top of memory) registers and MSI/MSI-x memory region, so we reserve 0xfe000000~0xffffffff (32MB below 4GB). Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12889/ Signed-off-by: Ralf Baechle --- arch/mips/loongson64/loongson-3/numa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 6f9e010cec4d..282c5a8c2fcd 100644 --- a/arch/mips/loongson64/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c @@ -213,10 +213,10 @@ static void __init node_mem_init(unsigned int node) BOOTMEM_DEFAULT); if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) { - /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */ + /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ reserve_bootmem_node(NODE_DATA(node), - (node_addrspace_offset | 0xff800000), - 8 << 20, BOOTMEM_DEFAULT); + (node_addrspace_offset | 0xfe000000), + 32 << 20, BOOTMEM_DEFAULT); } sparse_memory_present_with_active_regions(node); -- cgit v1.2.3-59-g8ed1b From 820880cdba0137baff6cc0e828c3c418c363ae44 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 17 Mar 2016 20:41:06 +0800 Subject: MIPS: Loongson-3: Fix build error after ld-version.sh modification Commit d5ece1cb074b2c ("Fix ld-version.sh to handle large 3rd version part") modifies the ld version description. This causes a build error on Loongson-3, so fix it. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: Huacai Chen Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12890/ Signed-off-by: Ralf Baechle --- arch/mips/loongson64/Platform | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/loongson64/Platform b/arch/mips/loongson64/Platform index 85d808924c94..0fce4608aa88 100644 --- a/arch/mips/loongson64/Platform +++ b/arch/mips/loongson64/Platform @@ -31,7 +31,7 @@ cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap # can't easily be used safely within the kbuild framework. # ifeq ($(call cc-ifversion, -ge, 0409, y), y) - ifeq ($(call ld-ifversion, -ge, 22500000, y), y) + ifeq ($(call ld-ifversion, -ge, 225000000, y), y) cflags-$(CONFIG_CPU_LOONGSON3) += \ $(call cc-option,-march=loongson3a -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) else -- cgit v1.2.3-59-g8ed1b From fa0c879ffc869e2597364c72080fd4756a96e99a Mon Sep 17 00:00:00 2001 From: Yanjiang Jin Date: Wed, 9 Dec 2015 11:15:27 +0800 Subject: MIPS: oprofile: Fix a preemption issue Use boot_cpu_type() instead of current_cpu_type() in oprofile_arch_init() to avoid the below warning, cpu_type is normally consistent in a MIPS SMP system. There are a few exceptions such as SGI servers where it is possible to mix R10000, R12000, R14000 and R16000 within certain constraints. Let's not worry about those now. BUG: using smp_processor_id() in preemptible [00000000] code: insmod/952 caller is oprofile_arch_init+0x30/0x194 [oprofile] CPU: 5 PID: 952 Comm: insmod Not tainted 4.1.13-WR8.0.0.0_standard #1 Stack : ffffffff80c10000 0000000000000001 8000000025bf0790 ffffffff80e10000 ffffffff80e50000 ffffffff80254e2c ffffffff80b64428 ffffffff80e10790 0000000000000000 ffffffff801caeb8 0000000000000045 0000000000000005 ffffffff80c10000 ffffffff801cb798 0000000000000000 ffffffff80e30000 0000000000000000 ffffffff801ff1c0 ffffffff80e2d2f8 000000000000000b ffffffff801cbba0 ffffffff80e107b0 ffffffff80a77828 0000000000000005 00000000000003b8 ffffffff80e2d2f8 800000040ad39960 ffffffff801f9950 0000000000000124 80000004093b7990 80000004093b7ab8 ffffffff80925108 ffffffff80b69a07 ffffffff80a6f0d0 8000000407240e00 ffffffff801cc934 000000000000005d ffffffff80159080 0000000000000005 00000000000003b8 ... Call Trace: [] show_stack+0xe8/0x108 [] dump_stack+0x8c/0xd8 [] check_preemption_disabled+0x110/0x118 [] oprofile_arch_init+0x30/0x194 [oprofile] [] oprofile_init+0x2c/0xc0 [oprofile] [] do_one_initcall+0xa0/0x1c0 [] do_init_module+0x80/0x1d8 [] load_module+0x1b74/0x2278 [] SyS_finit_module+0xcc/0xf0 [] handle_sysn32+0x44/0x70 [ralf@linux-mips.org: Correct commit message.] Signed-off-by: Yanjiang Jin Cc: rric@kernel.org Cc: jinyanjiang@gmail.com Cc: linux-mips@linux-mips.org Cc: oprofile-list@lists.sf.net Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11769/ Signed-off-by: Ralf Baechle --- arch/mips/oprofile/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index 3c9ec3ddca84..2f33992f6dff 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -77,7 +77,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) struct op_mips_model *lmodel = NULL; int res; - switch (current_cpu_type()) { + switch (boot_cpu_type()) { case CPU_5KC: case CPU_M14KC: case CPU_M14KEC: -- cgit v1.2.3-59-g8ed1b From 8d4925e9a5e5fb360b091b94a9682e02dfbf8e2b Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Mon, 21 Dec 2015 15:21:42 +0000 Subject: MIPS: dma-default: Defend against NULL dev in massage_gfp_flags This patch ensures that the dev parameter is checked for NULL before it is dereferenced in massage_gfp_flags. If dev is NULL, then fall back setting the GFP flag requested and available. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11919/ Signed-off-by: Ralf Baechle --- arch/mips/mm/dma-default.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 730d394ce5f0..cb557d28cb21 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -88,19 +88,20 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) else #endif #if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA) - if (dev->coherent_dma_mask < DMA_BIT_MASK(32)) + if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(32)) dma_flag = __GFP_DMA; else if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) dma_flag = __GFP_DMA32; else #endif #if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA) - if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(64)) dma_flag = __GFP_DMA32; else #endif #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32) - if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8)) + if (dev == NULL || + dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8)) dma_flag = __GFP_DMA; else #endif -- cgit v1.2.3-59-g8ed1b From 41fa29e4d8cf4150568a0fe9bb4d62229f9caed5 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Tue, 28 Apr 2015 12:53:35 -0700 Subject: MIPS64: R6: R2 emulation bugfix Error recovery pointers for fixups was improperly set as ".word" which is unsuitable for MIPS64. Replaced by STR(PTR) [ralf@linux-mips.org: Apply changes as requested in the review process.] Signed-off-by: Leonid Yegoshin Reviewed-by: James Hogan Reviewed-by: Markos Chandras Fixes: b0a668fb2038 ("MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6") Cc: macro@linux-mips.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: # 4.0+ Patchwork: https://patchwork.linux-mips.org/patch/9911/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-r2-to-r6-emul.c | 105 +++++++++++++++++----------------- 1 file changed, 53 insertions(+), 52 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 3fff89ae760b..625ee770b1aa 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1251,10 +1252,10 @@ fpu_emul: " j 10b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1326,10 +1327,10 @@ fpu_emul: " j 10b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1397,10 +1398,10 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1467,10 +1468,10 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1582,14 +1583,14 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" - " .word 5b,8b\n" - " .word 6b,8b\n" - " .word 7b,8b\n" - " .word 0b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" + STR(PTR) " 5b,8b\n" + STR(PTR) " 6b,8b\n" + STR(PTR) " 7b,8b\n" + STR(PTR) " 0b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1701,14 +1702,14 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" - " .word 5b,8b\n" - " .word 6b,8b\n" - " .word 7b,8b\n" - " .word 0b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" + STR(PTR) " 5b,8b\n" + STR(PTR) " 6b,8b\n" + STR(PTR) " 7b,8b\n" + STR(PTR) " 0b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1820,14 +1821,14 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" - " .word 5b,8b\n" - " .word 6b,8b\n" - " .word 7b,8b\n" - " .word 0b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" + STR(PTR) " 5b,8b\n" + STR(PTR) " 6b,8b\n" + STR(PTR) " 7b,8b\n" + STR(PTR) " 0b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -1938,14 +1939,14 @@ fpu_emul: " j 9b\n" " .previous\n" " .section __ex_table,\"a\"\n" - " .word 1b,8b\n" - " .word 2b,8b\n" - " .word 3b,8b\n" - " .word 4b,8b\n" - " .word 5b,8b\n" - " .word 6b,8b\n" - " .word 7b,8b\n" - " .word 0b,8b\n" + STR(PTR) " 1b,8b\n" + STR(PTR) " 2b,8b\n" + STR(PTR) " 3b,8b\n" + STR(PTR) " 4b,8b\n" + STR(PTR) " 5b,8b\n" + STR(PTR) " 6b,8b\n" + STR(PTR) " 7b,8b\n" + STR(PTR) " 0b,8b\n" " .previous\n" " .set pop\n" : "+&r"(rt), "=&r"(rs), @@ -2000,7 +2001,7 @@ fpu_emul: "j 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" - ".word 1b, 3b\n" + STR(PTR) " 1b,3b\n" ".previous\n" : "=&r"(res), "+&r"(err) : "r"(vaddr), "i"(SIGSEGV) @@ -2058,7 +2059,7 @@ fpu_emul: "j 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" - ".word 1b, 3b\n" + STR(PTR) " 1b,3b\n" ".previous\n" : "+&r"(res), "+&r"(err) : "r"(vaddr), "i"(SIGSEGV)); @@ -2119,7 +2120,7 @@ fpu_emul: "j 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" - ".word 1b, 3b\n" + STR(PTR) " 1b,3b\n" ".previous\n" : "=&r"(res), "+&r"(err) : "r"(vaddr), "i"(SIGSEGV) @@ -2182,7 +2183,7 @@ fpu_emul: "j 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" - ".word 1b, 3b\n" + STR(PTR) " 1b,3b\n" ".previous\n" : "+&r"(res), "+&r"(err) : "r"(vaddr), "i"(SIGSEGV)); -- cgit v1.2.3-59-g8ed1b From 8e85f275e934fe4e9be02c1d80583b042de5438c Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 7 Feb 2016 11:05:58 +0000 Subject: MIPS: memset.S: Disable code unused with non-R6 MIPS configs This complements commit 8c56208aff77 ("MIPS: lib: memset: Add MIPS R6 support"). Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12452/ Signed-off-by: Ralf Baechle --- arch/mips/lib/memset.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 8f0019a2e5c8..18a1ccd4d134 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -228,10 +228,12 @@ .hidden __memset .endif +#ifdef CONFIG_CPU_MIPSR6 .Lbyte_fixup\@: PTR_SUBU a2, $0, t0 jr ra PTR_ADDIU a2, 1 +#endif /* CONFIG_CPU_MIPSR6 */ .Lfirst_fixup\@: jr ra -- cgit v1.2.3-59-g8ed1b From 8a3c8b48aca8771bff3536e40aa26ffb311699d1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 15 Apr 2016 10:07:23 +0100 Subject: MIPS: Use copy_s.fmt rather than copy_u.fmt In revision 1.12 of the MSA specification, the copy_u.w instruction has been removed for MIPS32 & the copy_u.d instruction has been removed for MIPS64. Newer toolchains (eg. Codescape SDK essentials 2015.10) will complain about this like so: arch/mips/kernel/r4k_fpu.S:290: Error: opcode not supported on this processor: mips32r2 (mips32r2) `copy_u.w $1,$w26[3]' Since we always copy to the width of a GPR, simply use copy_s instead of copy_u to fix this. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Cc: # 4.3.x+ Patchwork: https://patchwork.linux-mips.org/patch/13061/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 24 ++++++++++++------------ arch/mips/kernel/r4k_fpu.S | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 867f924b05c7..b99b38862fcb 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -298,21 +298,21 @@ .set pop .endm - .macro copy_u_w ws, n + .macro copy_s_w ws, n .set push .set mips32r2 .set fp=64 .set msa - copy_u.w $1, $w\ws[\n] + copy_s.w $1, $w\ws[\n] .set pop .endm - .macro copy_u_d ws, n + .macro copy_s_d ws, n .set push .set mips64r2 .set fp=64 .set msa - copy_u.d $1, $w\ws[\n] + copy_s.d $1, $w\ws[\n] .set pop .endm @@ -346,8 +346,8 @@ #define STH_MSA_INSN 0x5800081f #define STW_MSA_INSN 0x5800082f #define STD_MSA_INSN 0x5800083f -#define COPY_UW_MSA_INSN 0x58f00056 -#define COPY_UD_MSA_INSN 0x58f80056 +#define COPY_SW_MSA_INSN 0x58b00056 +#define COPY_SD_MSA_INSN 0x58b80056 #define INSERT_W_MSA_INSN 0x59300816 #define INSERT_D_MSA_INSN 0x59380816 #else @@ -361,8 +361,8 @@ #define STH_MSA_INSN 0x78000825 #define STW_MSA_INSN 0x78000826 #define STD_MSA_INSN 0x78000827 -#define COPY_UW_MSA_INSN 0x78f00059 -#define COPY_UD_MSA_INSN 0x78f80059 +#define COPY_SW_MSA_INSN 0x78b00059 +#define COPY_SD_MSA_INSN 0x78b80059 #define INSERT_W_MSA_INSN 0x79300819 #define INSERT_D_MSA_INSN 0x79380819 #endif @@ -461,21 +461,21 @@ .set pop .endm - .macro copy_u_w ws, n + .macro copy_s_w ws, n .set push .set noat SET_HARDFLOAT .insn - .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11) + .word COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11) .set pop .endm - .macro copy_u_d ws, n + .macro copy_s_d ws, n .set push .set noat SET_HARDFLOAT .insn - .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11) + .word COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11) .set pop .endm diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 17732f876eff..56d86b09c917 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -244,17 +244,17 @@ LEAF(\name) .set push .set noat #ifdef CONFIG_64BIT - copy_u_d \wr, 1 + copy_s_d \wr, 1 EX sd $1, \off(\base) #elif defined(CONFIG_CPU_LITTLE_ENDIAN) - copy_u_w \wr, 2 + copy_s_w \wr, 2 EX sw $1, \off(\base) - copy_u_w \wr, 3 + copy_s_w \wr, 3 EX sw $1, (\off+4)(\base) #else /* CONFIG_CPU_BIG_ENDIAN */ - copy_u_w \wr, 2 + copy_s_w \wr, 2 EX sw $1, (\off+4)(\base) - copy_u_w \wr, 3 + copy_s_w \wr, 3 EX sw $1, \off(\base) #endif .set pop -- cgit v1.2.3-59-g8ed1b From ea1688573426adc2587ed52d086b51c7c62eaca3 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:24 +0100 Subject: MIPS: Fix MSA ld_*/st_* asm macros to use PTR_ADDU The MSA ld_*/st_* assembler macros for when the toolchain doesn't support MSA use addu to offset the base address. However it is a virtual memory pointer so fix it to use PTR_ADDU which expands to daddu for 64-bit kernels. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.3.y- Patchwork: https://patchwork.linux-mips.org/patch/13062/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index b99b38862fcb..e689b894353c 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -393,7 +393,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDB_MSA_INSN | (\wd << 6) .set pop .endm @@ -402,7 +402,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDH_MSA_INSN | (\wd << 6) .set pop .endm @@ -411,7 +411,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDW_MSA_INSN | (\wd << 6) .set pop .endm @@ -420,7 +420,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDD_MSA_INSN | (\wd << 6) .set pop .endm @@ -429,7 +429,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STB_MSA_INSN | (\wd << 6) .set pop .endm @@ -438,7 +438,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STH_MSA_INSN | (\wd << 6) .set pop .endm @@ -447,7 +447,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STW_MSA_INSN | (\wd << 6) .set pop .endm @@ -456,7 +456,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STD_MSA_INSN | (\wd << 6) .set pop .endm -- cgit v1.2.3-59-g8ed1b From 143e93d74e19febd491792cdd3aec3054883b776 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:25 +0100 Subject: MIPS: Fix MSA assembly with big thread offsets When lockdep is enabled on a 64-bit kernel the FPR offset into the thread structure exceeds the maximum range of the MSA ld.d/st.d instructions. For example THREAD_FPR31 = 4644 (instead of 2448), while the signed immediate field is only 10 bits with an implicit multiply by 8, giving a maximum offset of 511*8 = 4088. This isn't a problem when the toolchain doesn't support MSA as the ld_*/st_* macros perform the addition separately into $1 with [d]addui which has a 16bit signed immediate field. Fix the case where the toolchain does support MSA by doing a single addition of THREAD_FPR0 into $1 with [d]addui, and doing the ld_*/st_* relative to that. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13064/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 149 ++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 66 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index e689b894353c..637fccab5604 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -496,41 +496,52 @@ .endm #endif +#ifdef TOOLCHAIN_SUPPORTS_MSA +#define FPR_BASE_OFFS THREAD_FPR0 +#define FPR_BASE $1 +#else +#define FPR_BASE_OFFS 0 +#define FPR_BASE \thread +#endif + .macro msa_save_all thread - st_d 0, THREAD_FPR0, \thread - st_d 1, THREAD_FPR1, \thread - st_d 2, THREAD_FPR2, \thread - st_d 3, THREAD_FPR3, \thread - st_d 4, THREAD_FPR4, \thread - st_d 5, THREAD_FPR5, \thread - st_d 6, THREAD_FPR6, \thread - st_d 7, THREAD_FPR7, \thread - st_d 8, THREAD_FPR8, \thread - st_d 9, THREAD_FPR9, \thread - st_d 10, THREAD_FPR10, \thread - st_d 11, THREAD_FPR11, \thread - st_d 12, THREAD_FPR12, \thread - st_d 13, THREAD_FPR13, \thread - st_d 14, THREAD_FPR14, \thread - st_d 15, THREAD_FPR15, \thread - st_d 16, THREAD_FPR16, \thread - st_d 17, THREAD_FPR17, \thread - st_d 18, THREAD_FPR18, \thread - st_d 19, THREAD_FPR19, \thread - st_d 20, THREAD_FPR20, \thread - st_d 21, THREAD_FPR21, \thread - st_d 22, THREAD_FPR22, \thread - st_d 23, THREAD_FPR23, \thread - st_d 24, THREAD_FPR24, \thread - st_d 25, THREAD_FPR25, \thread - st_d 26, THREAD_FPR26, \thread - st_d 27, THREAD_FPR27, \thread - st_d 28, THREAD_FPR28, \thread - st_d 29, THREAD_FPR29, \thread - st_d 30, THREAD_FPR30, \thread - st_d 31, THREAD_FPR31, \thread .set push .set noat +#ifdef TOOLCHAIN_SUPPORTS_MSA + PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS +#endif + st_d 0, THREAD_FPR0 - FPR_BASE_OFFS, FPR_BASE + st_d 1, THREAD_FPR1 - FPR_BASE_OFFS, FPR_BASE + st_d 2, THREAD_FPR2 - FPR_BASE_OFFS, FPR_BASE + st_d 3, THREAD_FPR3 - FPR_BASE_OFFS, FPR_BASE + st_d 4, THREAD_FPR4 - FPR_BASE_OFFS, FPR_BASE + st_d 5, THREAD_FPR5 - FPR_BASE_OFFS, FPR_BASE + st_d 6, THREAD_FPR6 - FPR_BASE_OFFS, FPR_BASE + st_d 7, THREAD_FPR7 - FPR_BASE_OFFS, FPR_BASE + st_d 8, THREAD_FPR8 - FPR_BASE_OFFS, FPR_BASE + st_d 9, THREAD_FPR9 - FPR_BASE_OFFS, FPR_BASE + st_d 10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE + st_d 11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE + st_d 12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE + st_d 13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE + st_d 14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE + st_d 15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE + st_d 16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE + st_d 17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE + st_d 18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE + st_d 19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE + st_d 20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE + st_d 21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE + st_d 22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE + st_d 23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE + st_d 24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE + st_d 25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE + st_d 26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE + st_d 27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE + st_d 28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE + st_d 29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE + st_d 30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE + st_d 31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE SET_HARDFLOAT _cfcmsa $1, MSA_CSR sw $1, THREAD_MSA_CSR(\thread) @@ -543,40 +554,46 @@ SET_HARDFLOAT lw $1, THREAD_MSA_CSR(\thread) _ctcmsa MSA_CSR, $1 - .set pop - ld_d 0, THREAD_FPR0, \thread - ld_d 1, THREAD_FPR1, \thread - ld_d 2, THREAD_FPR2, \thread - ld_d 3, THREAD_FPR3, \thread - ld_d 4, THREAD_FPR4, \thread - ld_d 5, THREAD_FPR5, \thread - ld_d 6, THREAD_FPR6, \thread - ld_d 7, THREAD_FPR7, \thread - ld_d 8, THREAD_FPR8, \thread - ld_d 9, THREAD_FPR9, \thread - ld_d 10, THREAD_FPR10, \thread - ld_d 11, THREAD_FPR11, \thread - ld_d 12, THREAD_FPR12, \thread - ld_d 13, THREAD_FPR13, \thread - ld_d 14, THREAD_FPR14, \thread - ld_d 15, THREAD_FPR15, \thread - ld_d 16, THREAD_FPR16, \thread - ld_d 17, THREAD_FPR17, \thread - ld_d 18, THREAD_FPR18, \thread - ld_d 19, THREAD_FPR19, \thread - ld_d 20, THREAD_FPR20, \thread - ld_d 21, THREAD_FPR21, \thread - ld_d 22, THREAD_FPR22, \thread - ld_d 23, THREAD_FPR23, \thread - ld_d 24, THREAD_FPR24, \thread - ld_d 25, THREAD_FPR25, \thread - ld_d 26, THREAD_FPR26, \thread - ld_d 27, THREAD_FPR27, \thread - ld_d 28, THREAD_FPR28, \thread - ld_d 29, THREAD_FPR29, \thread - ld_d 30, THREAD_FPR30, \thread - ld_d 31, THREAD_FPR31, \thread - .endm +#ifdef TOOLCHAIN_SUPPORTS_MSA + PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS +#endif + ld_d 0, THREAD_FPR0 - FPR_BASE_OFFS, FPR_BASE + ld_d 1, THREAD_FPR1 - FPR_BASE_OFFS, FPR_BASE + ld_d 2, THREAD_FPR2 - FPR_BASE_OFFS, FPR_BASE + ld_d 3, THREAD_FPR3 - FPR_BASE_OFFS, FPR_BASE + ld_d 4, THREAD_FPR4 - FPR_BASE_OFFS, FPR_BASE + ld_d 5, THREAD_FPR5 - FPR_BASE_OFFS, FPR_BASE + ld_d 6, THREAD_FPR6 - FPR_BASE_OFFS, FPR_BASE + ld_d 7, THREAD_FPR7 - FPR_BASE_OFFS, FPR_BASE + ld_d 8, THREAD_FPR8 - FPR_BASE_OFFS, FPR_BASE + ld_d 9, THREAD_FPR9 - FPR_BASE_OFFS, FPR_BASE + ld_d 10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE + ld_d 11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE + ld_d 12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE + ld_d 13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE + ld_d 14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE + ld_d 15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE + ld_d 16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE + ld_d 17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE + ld_d 18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE + ld_d 19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE + ld_d 20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE + ld_d 21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE + ld_d 22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE + ld_d 23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE + ld_d 24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE + ld_d 25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE + ld_d 26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE + ld_d 27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE + ld_d 28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE + ld_d 29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE + ld_d 30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE + ld_d 31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE + .set pop + .endm + +#undef FPR_BASE_OFFS +#undef FPR_BASE .macro msa_init_upper wd #ifdef CONFIG_64BIT -- cgit v1.2.3-59-g8ed1b From 92e9953c5865b47281d74d43f08d7cecde11e58a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:26 +0100 Subject: MIPS: Fix MSA assembly warnings Building an MSA capable kernel with a toolchain that supports MSA produces warnings such as this: arch/mips/kernel/r4k_fpu.S:229: Warning: the `msa' extension requires 64-bit FPRs This is due to ".set msa" without ".set fp=64" in the non doubleword MSA load/store macros, since MSA requires the 64-bit FPU registers (FR=1). Add the missing fp=64 in these macros to silence the warnings. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13063/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 637fccab5604..6741673c92ca 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -235,6 +235,7 @@ .macro ld_b wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.b $w\wd, \off(\base) .set pop @@ -243,6 +244,7 @@ .macro ld_h wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.h $w\wd, \off(\base) .set pop @@ -251,6 +253,7 @@ .macro ld_w wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.w $w\wd, \off(\base) .set pop @@ -268,6 +271,7 @@ .macro st_b wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.b $w\wd, \off(\base) .set pop @@ -276,6 +280,7 @@ .macro st_h wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.h $w\wd, \off(\base) .set pop @@ -284,6 +289,7 @@ .macro st_w wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.w $w\wd, \off(\base) .set pop -- cgit v1.2.3-59-g8ed1b From 05490626d5f535baaaec60cdd37167f1a8031a9b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 15 Apr 2016 10:25:33 +0200 Subject: MIPS: Move definitions for 32/64-bit agonstic inline assembler to new file. Inspired by Markos Chandras' patch. I just didn't want do pull bitsops.h into pgtable.h. Signed-off-by: Ralf Baechle References: https://patchwork.linux-mips.org/patch/11052/ --- arch/mips/include/asm/bitops.h | 17 +---------------- arch/mips/include/asm/llsc.h | 28 ++++++++++++++++++++++++++++ arch/mips/include/asm/pgtable.h | 11 ++--------- 3 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 arch/mips/include/asm/llsc.h (limited to 'arch') diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index ce9666cf1499..fa57cef12a46 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -19,25 +19,10 @@ #include /* sigh ... */ #include #include +#include #include #include -#if _MIPS_SZLONG == 32 -#define SZLONG_LOG 5 -#define SZLONG_MASK 31UL -#define __LL "ll " -#define __SC "sc " -#define __INS "ins " -#define __EXT "ext " -#elif _MIPS_SZLONG == 64 -#define SZLONG_LOG 6 -#define SZLONG_MASK 63UL -#define __LL "lld " -#define __SC "scd " -#define __INS "dins " -#define __EXT "dext " -#endif - /* * These are the "slower" versions of the functions and are in bitops.c. * These functions call raw_local_irq_{save,restore}(). diff --git a/arch/mips/include/asm/llsc.h b/arch/mips/include/asm/llsc.h new file mode 100644 index 000000000000..c6d17d171147 --- /dev/null +++ b/arch/mips/include/asm/llsc.h @@ -0,0 +1,28 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Macros for 32/64-bit neutral inline assembler + */ + +#ifndef __ASM_LLSC_H +#define __ASM_LLSC_H + +#if _MIPS_SZLONG == 32 +#define SZLONG_LOG 5 +#define SZLONG_MASK 31UL +#define __LL "ll " +#define __SC "sc " +#define __INS "ins " +#define __EXT "ext " +#elif _MIPS_SZLONG == 64 +#define SZLONG_LOG 6 +#define SZLONG_MASK 63UL +#define __LL "lld " +#define __SC "scd " +#define __INS "dins " +#define __EXT "dext " +#endif + +#endif /* __ASM_LLSC_H */ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 9a4fe0133ff1..25b1c1c08cbc 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -187,23 +187,16 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) * For SMP, multiple CPUs can race, so we need to do * this atomically. */ -#ifdef CONFIG_64BIT -#define LL_INSN "lld" -#define SC_INSN "scd" -#else /* CONFIG_32BIT */ -#define LL_INSN "ll" -#define SC_INSN "sc" -#endif unsigned long page_global = _PAGE_GLOBAL; unsigned long tmp; __asm__ __volatile__ ( " .set push\n" " .set noreorder\n" - "1: " LL_INSN " %[tmp], %[buddy]\n" + "1: " __LL " %[tmp], %[buddy]\n" " bnez %[tmp], 2f\n" " or %[tmp], %[tmp], %[global]\n" - " " SC_INSN " %[tmp], %[buddy]\n" + " " __SC " %[tmp], %[buddy]\n" " beqz %[tmp], 1b\n" " nop\n" "2:\n" -- cgit v1.2.3-59-g8ed1b From 128639395b2ceacc6a56a0141d0261012bfe04d3 Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Mon, 7 Sep 2015 06:42:30 -0400 Subject: MIPS: Adjust set_pte() SMP fix to handle R10000_LLSC_WAR Update the recent changes to set_pte() that were added in 46011e6ea392 to handle R10000_LLSC_WAR, and format the assembly to match other areas of the MIPS tree using the same WAR. This also incorporates a patch recently sent in my Markos Chandras, "Remove local LL/SC preprocessor variants", so that patch doesn't need to be applied if this one is accepted. Signed-off-by: Joshua Kinard Fixes: 46011e6ea392 ("MIPS: Make set_pte() SMP safe.) Cc: David Daney Cc: Linux/MIPS Patchwork: https://patchwork.linux-mips.org/patch/11103/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable.h | 45 +++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 25b1c1c08cbc..75c29cff0f99 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -190,20 +190,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) unsigned long page_global = _PAGE_GLOBAL; unsigned long tmp; - __asm__ __volatile__ ( - " .set push\n" - " .set noreorder\n" - "1: " __LL " %[tmp], %[buddy]\n" - " bnez %[tmp], 2f\n" - " or %[tmp], %[tmp], %[global]\n" - " " __SC " %[tmp], %[buddy]\n" - " beqz %[tmp], 1b\n" - " nop\n" - "2:\n" - " .set pop" - : [buddy] "+m" (buddy->pte), - [tmp] "=&r" (tmp) + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__ ( + " .set arch=r4000 \n" + " .set push \n" + " .set noreorder \n" + "1:" __LL "%[tmp], %[buddy] \n" + " bnez %[tmp], 2f \n" + " or %[tmp], %[tmp], %[global] \n" + __SC "%[tmp], %[buddy] \n" + " beqzl %[tmp], 1b \n" + " nop \n" + "2: \n" + " .set pop \n" + " .set mips0 \n" + : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) : [global] "r" (page_global)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__ ( + " .set "MIPS_ISA_ARCH_LEVEL" \n" + " .set push \n" + " .set noreorder \n" + "1:" __LL "%[tmp], %[buddy] \n" + " bnez %[tmp], 2f \n" + " or %[tmp], %[tmp], %[global] \n" + __SC "%[tmp], %[buddy] \n" + " beqz %[tmp], 1b \n" + " nop \n" + "2: \n" + " .set pop \n" + " .set mips0 \n" + : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) + : [global] "r" (page_global)); + } #else /* !CONFIG_SMP */ if (pte_none(*buddy)) pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; -- cgit v1.2.3-59-g8ed1b From 32eb6e8bee147b45e5e59230630d59541ccbb6e5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 28 Apr 2016 17:06:16 +0100 Subject: MIPS: Netlogic: Fix CP0_EBASE redefinition warnings A couple of netlogic assembly files define CP0_EBASE to $15, the same as CP0_PRID in mipsregs.h, and use it for accessing both CP0_PRId and CP0_EBase registers. However commit 609cf6f2291a ("MIPS: CPS: Early debug using an ns16550-compatible UART") added a different definition of CP0_EBASE to mipsregs.h, which included a register select of 1. This causes harmless build warnings like the following: arch/mips/netlogic/common/reset.S:53:0: warning: "CP0_EBASE" redefined #define CP0_EBASE $15 ^ In file included from arch/mips/netlogic/common/reset.S:41:0: ./arch/mips/include/asm/mipsregs.h:63:0: note: this is the location of the previous definition #define CP0_EBASE $15, 1 ^ Update the code to use the definitions from mipsregs.h for accessing both registers. Fixes: 609cf6f2291a ("MIPS: CPS: Early debug using an ns16550-compatible UART") Signed-off-by: James Hogan Acked-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13183/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/reset.S | 11 +++++------ arch/mips/netlogic/common/smpboot.S | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index edbab9b8691f..c474981a6c0d 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -50,7 +50,6 @@ #include #include -#define CP0_EBASE $15 #define SYS_CPU_COHERENT_BASE CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \ SYS_CPU_NONCOHERENT_MODE * 4 @@ -92,7 +91,7 @@ * registers. On XLPII CPUs, usual cache instructions work. */ .macro xlp_flush_l1_dcache - mfc0 t0, CP0_EBASE, 0 + mfc0 t0, CP0_PRID andi t0, t0, PRID_IMP_MASK slt t1, t0, 0x1200 beqz t1, 15f @@ -171,7 +170,7 @@ FEXPORT(nlm_reset_entry) nop 1: /* Entry point on core wakeup */ - mfc0 t0, CP0_EBASE, 0 /* processor ID */ + mfc0 t0, CP0_PRID /* processor ID */ andi t0, PRID_IMP_MASK li t1, 0x1500 /* XLP 9xx */ beq t0, t1, 2f /* does not need to set coherent */ @@ -182,8 +181,8 @@ FEXPORT(nlm_reset_entry) nop /* set bit in SYS coherent register for the core */ - mfc0 t0, CP0_EBASE, 1 - mfc0 t1, CP0_EBASE, 1 + mfc0 t0, CP0_EBASE + mfc0 t1, CP0_EBASE srl t1, 5 andi t1, 0x3 /* t1 <- node */ li t2, 0x40000 @@ -232,7 +231,7 @@ EXPORT(nlm_boot_siblings) * NOTE: All GPR contents are lost after the mtcr above! */ - mfc0 v0, CP0_EBASE, 1 + mfc0 v0, CP0_EBASE andi v0, 0x3ff /* v0 <- node/core */ /* diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 805355b0bd05..f0cc4c9de2bb 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -48,8 +48,6 @@ #include #include -#define CP0_EBASE $15 - .set noreorder .set noat .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ @@ -86,7 +84,7 @@ NESTED(nlm_boot_secondary_cpus, 16, sp) PTR_L gp, 0(t1) /* a0 has the processor id */ - mfc0 a0, CP0_EBASE, 1 + mfc0 a0, CP0_EBASE andi a0, 0x3ff /* a0 <- node/core */ PTR_LA t0, nlm_early_init_secondary jalr t0 -- cgit v1.2.3-59-g8ed1b From 8f4d4d1bfb47014f324309781917e4fd3eb6a316 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Tue, 26 Jan 2016 08:27:15 +0100 Subject: MIPS: ath79: Add support for DTB passed using the UHI boot protocol This is needed for bootloader supporting UHI and to support appended DTB. Signed-off-by: Alban Bedel Cc: Felix Fietkau Cc: Antony Pavlov Cc: Gabor Juhos Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12230/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/setup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index be451ee4a5ea..0e60b0f4c69f 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -203,6 +203,8 @@ void __init plat_mem_setup(void) fdt_start = fw_getenvl("fdt_start"); if (fdt_start) __dt_setup_arch((void *)KSEG0ADDR(fdt_start)); + else if (fw_arg0 == -2) + __dt_setup_arch((void *)KSEG0ADDR(fw_arg1)); #ifdef CONFIG_BUILTIN_DTB else __dt_setup_arch(__dtb_start); -- cgit v1.2.3-59-g8ed1b From ea3a7085bfa85ad52118822df73123b7e7056dab Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Tue, 26 Jan 2016 08:27:16 +0100 Subject: MIPS: ath79: Remove the builtin DTB support Now that appended DTB is usable we can drop the builtin DTB support. Signed-off-by: Alban Bedel Cc: Felix Fietkau Cc: Antony Pavlov Cc: Gabor Juhos Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12231/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/Kconfig | 12 ------------ arch/mips/ath79/setup.c | 4 ---- arch/mips/boot/dts/qca/Makefile | 3 --- 3 files changed, 19 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index 13c04cf54afa..dfc60209dc63 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -71,18 +71,6 @@ config ATH79_MACH_UBNT_XM Say 'Y' here if you want your kernel to support the Ubiquiti Networks XM (rev 1.0) board. -choice - prompt "Build a DTB in the kernel" - optional - help - Select a devicetree that should be built into the kernel. - - config DTB_TL_WR1043ND_V1 - bool "TL-WR1043ND Version 1" - select BUILTIN_DTB - select SOC_AR913X -endchoice - endmenu config SOC_AR71XX diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 0e60b0f4c69f..906ddace159a 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -205,10 +205,6 @@ void __init plat_mem_setup(void) __dt_setup_arch((void *)KSEG0ADDR(fdt_start)); else if (fw_arg0 == -2) __dt_setup_arch((void *)KSEG0ADDR(fw_arg1)); -#ifdef CONFIG_BUILTIN_DTB - else - __dt_setup_arch(__dtb_start); -#endif ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, AR71XX_RESET_SIZE); diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile index 2d61455d585d..14bd22514283 100644 --- a/arch/mips/boot/dts/qca/Makefile +++ b/arch/mips/boot/dts/qca/Makefile @@ -1,9 +1,6 @@ # All DTBs dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb -# Select a DTB to build in the kernel -obj-$(CONFIG_DTB_TL_WR1043ND_V1) += ar9132_tl_wr1043nd_v1.dtb.o - # Force kbuild to make empty built-in.o if necessary obj- += dummy.o -- cgit v1.2.3-59-g8ed1b From b3f0a250d6eda645cee719cc11ea70e28f62145c Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Tue, 26 Jan 2016 09:38:29 +0100 Subject: MIPS: ath79: Add zboot debug serial support Reuse the early printk code to support the serial in zboot. We copy early_printk.c instead of referencing it because we need to build a different object file for the normal kernel and zboot. Signed-off-by: Alban Bedel Cc: Andrew Bresticker Cc: Alex Smith Cc: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12234/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/boot/compressed/Makefile | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 04c5e9c28fba..c049c0667559 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -137,7 +137,7 @@ config ATH79 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_MIPS16 - select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_ZBOOT_UART_PROM select USE_OF help Support for the Atheros AR71XX/AR724X/AR913X SoCs. diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 309d2ad67e4d..90aca95fe314 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -37,8 +37,13 @@ vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/dbg.o vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM) += $(obj)/uart-prom.o vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o +vmlinuzobjs-$(CONFIG_ATH79) += $(obj)/uart-ath79.o endif +extra-y += uart-ath79.c +$(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c + $(call cmd,shipped) + vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o extra-y += ashldi3.c bswapsi.c -- cgit v1.2.3-59-g8ed1b From 81424d0ad0d41f05049aac6d4959d17a5a3c69c8 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Tue, 26 Jan 2016 09:39:30 +0100 Subject: MIPS: ath79: Use the reset controller to restart OF machines Don't set _machine_restart() on OF machines as the reset driver now provides a system restart handler. Signed-off-by: Alban Bedel Cc: Felix Fietkau Cc: Antony Pavlov Cc: Gabor Juhos Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12235/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/setup.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 906ddace159a..01808e85e263 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -213,10 +213,11 @@ void __init plat_mem_setup(void) ath79_detect_sys_type(); ath79_ddr_ctrl_init(); - if (mips_machtype != ATH79_MACH_GENERIC_OF) + if (mips_machtype != ATH79_MACH_GENERIC_OF) { detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); - - _machine_restart = ath79_restart; + /* OF machines should use the reset driver */ + _machine_restart = ath79_restart; + } _machine_halt = ath79_halt; pm_power_off = ath79_halt; } -- cgit v1.2.3-59-g8ed1b From 9329c154e4a8a253347829c1d8cc416061cc055a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 27 Jan 2016 18:07:00 +0100 Subject: MIPS: Octeon: Use __flush_cache_all instead of flush_cache_all. flush_cache_all will go away. Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 42412ba0f3bf..61a60e424424 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -242,7 +242,7 @@ static int octeon_cpu_disable(void) cpumask_clear_cpu(cpu, &cpu_callin_map); octeon_fixup_irqs(); - flush_cache_all(); + __flush_cache_all(); local_flush_tlb_all(); return 0; -- cgit v1.2.3-59-g8ed1b From 7c8196fd43e41e7b699d2f7a54bafd10dd2f65bb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 27 Jan 2016 18:16:15 +0100 Subject: MIPS: MSP71xx: Use __flush_cache_all instead of flush_cache_all. Flushing caches is probably sensible on reset but flush_cache_all has been a no-op for a very long time. Signed-off-by: Ralf Baechle --- arch/mips/pmcs-msp71xx/msp_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c index 9d293b3e9130..a63b73610fd4 100644 --- a/arch/mips/pmcs-msp71xx/msp_setup.c +++ b/arch/mips/pmcs-msp71xx/msp_setup.c @@ -118,7 +118,7 @@ void msp_restart(char *command) /* No chip-specific reset code, just jump to the ROM reset vector */ set_c0_status(ST0_BEV | ST0_ERL); change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); + __flush_cache_all(); write_c0_wired(0); __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -- cgit v1.2.3-59-g8ed1b From a48ac3a131c1675de4c8293f59f6864db2a83240 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 27 Jan 2016 18:39:33 +0100 Subject: MIPS: VR41xx: Use __flush_cache_all instead of flush_cache_all. It's probably a good idea to flush caches before reset and by the time this code was written flush_cache_all did actually still do something. Signed-off-by: Ralf Baechle --- arch/mips/vr41xx/common/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index d7f755833c3f..39a0db3e2b34 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -73,7 +73,7 @@ static inline void software_reset(void) default: set_c0_status(ST0_BEV | ST0_ERL); change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); + __flush_cache_all(); write_c0_wired(0); __asm__("jr %0"::"r"(0xbfc00000)); break; -- cgit v1.2.3-59-g8ed1b From 429365b2a1a90b593a730f54819a4c5dfd98553b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 27 Jan 2016 19:02:12 +0100 Subject: MIPS: Loongson64: Remove call to flush_cache_all(). flush_cache_all() is a nop and loongson 3 is fully coherent. Signed-off-by: Ralf Baechle --- arch/mips/loongson64/loongson-3/smp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index 509832a9836c..b913cd240d77 100644 --- a/arch/mips/loongson64/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c @@ -421,7 +421,6 @@ static int loongson3_cpu_disable(void) local_irq_save(flags); fixup_irqs(); local_irq_restore(flags); - flush_cache_all(); local_flush_tlb_all(); return 0; -- cgit v1.2.3-59-g8ed1b From 34ae8e3688fb8af2afaf52b78c6f20c74c6ae650 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 28 Jan 2016 14:26:00 +0100 Subject: MIPS: highmem: Turn flush_cache_kmaps into a no-op. It was calling flush_cache_all() which is a no-op since a long time anyway and which was overkill in the old days when it was actually doing something because only the D-cache needs to be flushed, never the I-cache, never the S-cache. Since however highmem on MIPS is still only supported on processors that don't suffer from cache aliases, we could turn flush_cache_kmaps() into a no-op - but for paranoia's sake we rather make it BUG_ON(cpu_has_dc_aliases()). Signed-off-by: Ralf Baechle --- arch/mips/include/asm/highmem.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h index 01880b34a209..64f2500d891b 100644 --- a/arch/mips/include/asm/highmem.h +++ b/arch/mips/include/asm/highmem.h @@ -19,8 +19,10 @@ #ifdef __KERNEL__ +#include #include #include +#include #include /* undef for production */ @@ -50,7 +52,7 @@ extern void *kmap_atomic(struct page *page); extern void __kunmap_atomic(void *kvaddr); extern void *kmap_atomic_pfn(unsigned long pfn); -#define flush_cache_kmaps() flush_cache_all() +#define flush_cache_kmaps() BUG_ON(cpu_has_dc_aliases) extern void kmap_init(void); -- cgit v1.2.3-59-g8ed1b From b8c8f665076604762fd15eb815f2fd75eb511b2e Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 14:43:41 -0800 Subject: MIPS: Add CPU identifiers and probing for Cavium CN73xx and CNF75xx processors. Add new processor identifiers for Cavium CN73xx and CNF75xx processors, and probe for them in cpu-probe.c Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12311/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 2 ++ arch/mips/kernel/cpu-probe.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a97ca97285ec..7bea0f3bf9ee 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -169,6 +169,8 @@ #define PRID_IMP_CAVIUM_CNF71XX 0x9400 #define PRID_IMP_CAVIUM_CN78XX 0x9500 #define PRID_IMP_CAVIUM_CN70XX 0x9600 +#define PRID_IMP_CAVIUM_CN73XX 0x9700 +#define PRID_IMP_CAVIUM_CNF75XX 0x9800 /* * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_* diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b725b713b9f8..9ad6157e23de 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1481,6 +1481,8 @@ platform: set_elf_platform(cpu, "octeon2"); break; case PRID_IMP_CAVIUM_CN70XX: + case PRID_IMP_CAVIUM_CN73XX: + case PRID_IMP_CAVIUM_CNF75XX: case PRID_IMP_CAVIUM_CN78XX: c->cputype = CPU_CAVIUM_OCTEON3; __cpu_name[cpu] = "Cavium Octeon III"; -- cgit v1.2.3-59-g8ed1b From 58546e3b735cc9f695bba1559be76a68b072761f Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 17:46:53 -0800 Subject: MIPS: OCTEON: Remove dead code from cvmx-sysinfo. Get rid of the long unused code. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12318/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 72 ++---------------------- arch/mips/include/asm/octeon/cvmx-sysinfo.h | 30 +--------- 2 files changed, 5 insertions(+), 97 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c index 3d17fac29359..cc1b1d2a6fa1 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c +++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c @@ -32,86 +32,22 @@ #include #include -#include #include -/** +/* * This structure defines the private state maintained by sysinfo module. - * */ -static struct { - struct cvmx_sysinfo sysinfo; /* system information */ - cvmx_spinlock_t lock; /* mutex spinlock */ - -} state = { - .lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER -}; - +static struct cvmx_sysinfo sysinfo; /* system information */ /* - * Global variables that define the min/max of the memory region set - * up for 32 bit userspace access. - */ -uint64_t linux_mem32_min; -uint64_t linux_mem32_max; -uint64_t linux_mem32_wired; -uint64_t linux_mem32_offset; - -/** - * This function returns the application information as obtained + * Returns the application information as obtained * by the bootloader. This provides the core mask of the cores * running the same application image, as well as the physical * memory regions available to the core. - * - * Returns Pointer to the boot information structure - * */ struct cvmx_sysinfo *cvmx_sysinfo_get(void) { - return &(state.sysinfo); + return &sysinfo; } EXPORT_SYMBOL(cvmx_sysinfo_get); -/** - * This function is used in non-simple executive environments (such as - * Linux kernel, u-boot, etc.) to configure the minimal fields that - * are required to use simple executive files directly. - * - * Locking (if required) must be handled outside of this - * function - * - * @phy_mem_desc_ptr: - * Pointer to global physical memory descriptor - * (bootmem descriptor) @board_type: Octeon board - * type enumeration - * - * @board_rev_major: - * Board major revision - * @board_rev_minor: - * Board minor revision - * @cpu_clock_hz: - * CPU clock freqency in hertz - * - * Returns 0: Failure - * 1: success - */ -int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, - uint16_t board_type, - uint8_t board_rev_major, - uint8_t board_rev_minor, - uint32_t cpu_clock_hz) -{ - - /* The sysinfo structure was already initialized */ - if (state.sysinfo.board_type) - return 0; - - memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo)); - state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr; - state.sysinfo.board_type = board_type; - state.sysinfo.board_rev_major = board_rev_major; - state.sysinfo.board_rev_minor = board_rev_minor; - state.sysinfo.cpu_clock_hz = cpu_clock_hz; - - return 1; -} diff --git a/arch/mips/include/asm/octeon/cvmx-sysinfo.h b/arch/mips/include/asm/octeon/cvmx-sysinfo.h index 2131197422e5..78cd64ad79c7 100644 --- a/arch/mips/include/asm/octeon/cvmx-sysinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-sysinfo.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2008 Cavium Networks + * Copyright (c) 2003-2016 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -121,32 +121,4 @@ struct cvmx_sysinfo { extern struct cvmx_sysinfo *cvmx_sysinfo_get(void); -/** - * This function is used in non-simple executive environments (such as - * Linux kernel, u-boot, etc.) to configure the minimal fields that - * are required to use simple executive files directly. - * - * Locking (if required) must be handled outside of this - * function - * - * @phy_mem_desc_ptr: Pointer to global physical memory descriptor - * (bootmem descriptor) @board_type: Octeon board - * type enumeration - * - * @board_rev_major: - * Board major revision - * @board_rev_minor: - * Board minor revision - * @cpu_clock_hz: - * CPU clock freqency in hertz - * - * Returns 0: Failure - * 1: success - */ -extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, - uint16_t board_type, - uint8_t board_rev_major, - uint8_t board_rev_minor, - uint32_t cpu_clock_hz); - #endif /* __CVMX_SYSINFO_H__ */ -- cgit v1.2.3-59-g8ed1b From 7d52ab163c75bb830185f7ea12bae1db87f12b56 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 17:46:54 -0800 Subject: MIPS: OCTEON: Extend number of supported CPUs past 32 To support more than 48 CPUs, the bootinfo structure grows a new coremask structure. Add the definition of the structure and add it to struct cvmx_bootinfo. In prom_init(), copy the new coremask data into the sysinfo structure, and use it in smp_setup(). Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12319/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 19 +++++- arch/mips/cavium-octeon/smp.c | 4 +- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 14 ++++- arch/mips/include/asm/octeon/cvmx-coremask.h | 89 ++++++++++++++++++++++++++++ arch/mips/include/asm/octeon/cvmx-sysinfo.h | 7 ++- 5 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 arch/mips/include/asm/octeon/cvmx-coremask.h (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index cd7101fb6227..9c6ad2fab344 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -637,9 +637,22 @@ void __init prom_init(void) sysinfo = cvmx_sysinfo_get(); memset(sysinfo, 0, sizeof(*sysinfo)); sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20; - sysinfo->phy_mem_desc_ptr = - cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr); - sysinfo->core_mask = octeon_bootinfo->core_mask; + sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr); + + if ((octeon_bootinfo->major_version > 1) || + (octeon_bootinfo->major_version == 1 && + octeon_bootinfo->minor_version >= 4)) + cvmx_coremask_copy(&sysinfo->core_mask, + &octeon_bootinfo->ext_core_mask); + else + cvmx_coremask_set64(&sysinfo->core_mask, + octeon_bootinfo->core_mask); + + /* Some broken u-boot pass garbage in upper bits, clear them out */ + if (!OCTEON_IS_MODEL(OCTEON_CN78XX)) + for (i = 512; i < 1024; i++) + cvmx_coremask_clear_core(&sysinfo->core_mask, i); + sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr; sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz; sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2; diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 61a60e424424..42395c561aa5 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -103,6 +103,8 @@ static void octeon_smp_setup(void) int cpus; int id; int core_mask = octeon_get_boot_coremask(); + struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get(); + #ifdef CONFIG_HOTPLUG_CPU unsigned int num_cores = cvmx_octeon_num_cores(); #endif @@ -119,7 +121,7 @@ static void octeon_smp_setup(void) /* The present CPUs get the lowest CPU numbers. */ cpus = 1; for (id = 0; id < NR_CPUS; id++) { - if ((id != coreid) && (core_mask & (1 << id))) { + if ((id != coreid) && cvmx_coremask_is_core_set(&sysinfo->core_mask, id)) { set_cpu_possible(cpus, true); set_cpu_present(cpus, true); __cpu_number_map[id] = cpus; diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index d92cf59bdae6..c455d34f5a4f 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -32,6 +32,8 @@ #ifndef __CVMX_BOOTINFO_H__ #define __CVMX_BOOTINFO_H__ +#include "cvmx-coremask.h" + /* * Current major and minor versions of the CVMX bootinfo block that is * passed from the bootloader to the application. This is versioned @@ -39,7 +41,7 @@ * versions. */ #define CVMX_BOOTINFO_MAJ_VER 1 -#define CVMX_BOOTINFO_MIN_VER 3 +#define CVMX_BOOTINFO_MIN_VER 4 #if (CVMX_BOOTINFO_MAJ_VER == 1) #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20 @@ -124,6 +126,13 @@ struct cvmx_bootinfo { */ uint64_t fdt_addr; #endif +#if (CVMX_BOOTINFO_MIN_VER >= 4) + /* + * Coremask used for processors with more than 32 cores + * or with OCI. This replaces core_mask. + */ + struct cvmx_coremask ext_core_mask; +#endif #else /* __BIG_ENDIAN */ /* * Little-Endian: When the CPU mode is switched to @@ -177,6 +186,9 @@ struct cvmx_bootinfo { #if (CVMX_BOOTINFO_MIN_VER >= 3) uint64_t fdt_addr; #endif +#if (CVMX_BOOTINFO_MIN_VER >= 4) + struct cvmx_coremask ext_core_mask; +#endif #endif }; diff --git a/arch/mips/include/asm/octeon/cvmx-coremask.h b/arch/mips/include/asm/octeon/cvmx-coremask.h new file mode 100644 index 000000000000..097dc096db84 --- /dev/null +++ b/arch/mips/include/asm/octeon/cvmx-coremask.h @@ -0,0 +1,89 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2016 Cavium Inc. (support@cavium.com). + * + */ + +/* + * Module to support operations on bitmap of cores. Coremask can be used to + * select a specific core, a group of cores, or all available cores, for + * initialization and differentiation of roles within a single shared binary + * executable image. + * + * The core numbers used in this file are the same value as what is found in + * the COP0_EBASE register and the rdhwr 0 instruction. + * + * For the CN78XX and other multi-node environments the core numbers are not + * contiguous. The core numbers for the CN78XX are as follows: + * + * Node 0: Cores 0 - 47 + * Node 1: Cores 128 - 175 + * Node 2: Cores 256 - 303 + * Node 3: Cores 384 - 431 + * + */ + +#ifndef __CVMX_COREMASK_H__ +#define __CVMX_COREMASK_H__ + +#define CVMX_MIPS_MAX_CORES 1024 +/* bits per holder */ +#define CVMX_COREMASK_ELTSZ 64 + +/* cvmx_coremask_t's size in u64 */ +#define CVMX_COREMASK_BMPSZ (CVMX_MIPS_MAX_CORES / CVMX_COREMASK_ELTSZ) + + +/* cvmx_coremask_t */ +struct cvmx_coremask { + u64 coremask_bitmap[CVMX_COREMASK_BMPSZ]; +}; + +/* + * Is ``core'' set in the coremask? + */ +static inline bool cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm, + int core) +{ + int n, i; + + n = core % CVMX_COREMASK_ELTSZ; + i = core / CVMX_COREMASK_ELTSZ; + + return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0; +} + +/* + * Make a copy of a coremask + */ +static inline void cvmx_coremask_copy(struct cvmx_coremask *dest, + const struct cvmx_coremask *src) +{ + memcpy(dest, src, sizeof(*dest)); +} + +/* + * Set the lower 64-bit of the coremask. + */ +static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm, + uint64_t coremask_64) +{ + pcm->coremask_bitmap[0] = coremask_64; +} + +/* + * Clear ``core'' from the coremask. + */ +static inline void cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core) +{ + int n, i; + + n = core % CVMX_COREMASK_ELTSZ; + i = core / CVMX_COREMASK_ELTSZ; + pcm->coremask_bitmap[i] &= ~(1ull << n); +} + +#endif /* __CVMX_COREMASK_H__ */ diff --git a/arch/mips/include/asm/octeon/cvmx-sysinfo.h b/arch/mips/include/asm/octeon/cvmx-sysinfo.h index 78cd64ad79c7..c6c3ee39c69d 100644 --- a/arch/mips/include/asm/octeon/cvmx-sysinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-sysinfo.h @@ -32,6 +32,8 @@ #ifndef __CVMX_SYSINFO_H__ #define __CVMX_SYSINFO_H__ +#include "cvmx-coremask.h" + #define OCTEON_SERIAL_LEN 20 /** * Structure describing application specific information. @@ -50,8 +52,7 @@ struct cvmx_sysinfo { uint64_t system_dram_size; /* ptr to memory descriptor block */ - void *phy_mem_desc_ptr; - + uint64_t phy_mem_desc_addr; /* Application image specific variables */ /* stack top address (virtual) */ @@ -63,7 +64,7 @@ struct cvmx_sysinfo { /* heap size in bytes */ uint32_t heap_size; /* coremask defining cores running application */ - uint32_t core_mask; + struct cvmx_coremask core_mask; /* Deprecated, use cvmx_coremask_first_core() to select init core */ uint32_t init_core; -- cgit v1.2.3-59-g8ed1b From 2253e0b9d991e82210dd08c89bf91584ad25f993 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:06 -0800 Subject: MIPS: OCTEON: Remove some code limiting NR_IRQS to 255 Follow-on patches for OCTEON III will increase the number of irqs to potentially more than 256. Increase the width of the octeon_irq_ciu_to_irq to int to be able to handle this case. Remove the hacky code that verified that u8 would not be overflowed. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12495/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-irq.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 4f9eb0576884..bc30d3a90b2f 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2014 Cavium, Inc. + * Copyright (C) 2004-2016 Cavium, Inc. */ #include @@ -28,7 +28,7 @@ struct octeon_irq_ciu_domain_data { int num_sum; /* number of sum registers (2 or 3). */ }; -static __read_mostly u8 octeon_irq_ciu_to_irq[8][64]; +static __read_mostly int octeon_irq_ciu_to_irq[8][64]; struct octeon_ciu_chip_data { union { @@ -1158,16 +1158,6 @@ static struct irq_chip *octeon_irq_ciu_chip; static struct irq_chip *octeon_irq_ciu_chip_edge; static struct irq_chip *octeon_irq_gpio_chip; -static bool octeon_irq_virq_in_range(unsigned int virq) -{ - /* We cannot let it overflow the mapping array. */ - if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0]))) - return true; - - WARN_ONCE(true, "virq out of range %u.\n", virq); - return false; -} - static int octeon_irq_ciu_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) { @@ -1176,13 +1166,6 @@ static int octeon_irq_ciu_map(struct irq_domain *d, unsigned int bit = hw & 63; struct octeon_irq_ciu_domain_data *dd = d->host_data; - if (!octeon_irq_virq_in_range(virq)) - return -EINVAL; - - /* Don't map irq if it is reserved for GPIO. */ - if (line == 0 && bit >= 16 && bit <32) - return 0; - if (line >= dd->num_sum || octeon_irq_ciu_to_irq[line][bit] != 0) return -EINVAL; @@ -1215,9 +1198,6 @@ static int octeon_irq_gpio_map(struct irq_domain *d, unsigned int line, bit; int r; - if (!octeon_irq_virq_in_range(virq)) - return -EINVAL; - line = (hw + gpiod->base_hwirq) >> 6; bit = (hw + gpiod->base_hwirq) & 63; if (line > ARRAY_SIZE(octeon_irq_ciu_to_irq) || @@ -1899,9 +1879,6 @@ static int octeon_irq_ciu2_map(struct irq_domain *d, unsigned int line = hw >> 6; unsigned int bit = hw & 63; - if (!octeon_irq_virq_in_range(virq)) - return -EINVAL; - /* * Don't map irq if it is reserved for GPIO. * (Line 7 are the GPIO lines.) -- cgit v1.2.3-59-g8ed1b From 1d2753a66acbb101a0ec495cd13b9031ac1b171f Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:07 -0800 Subject: MIPS: Select CONFIG_HANDLE_DOMAIN_IRQ and make it work. Per the subject, always select HANDLE_DOMAIN_IRQ, and implement set_irq_regs() so that it actually works. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12496/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/irq_regs.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c049c0667559..2352917a47a1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -62,6 +62,7 @@ config MIPS select HAVE_IRQ_TIME_ACCOUNTING select GENERIC_TIME_VSYSCALL select ARCH_CLOCKSOURCE_DATA + select HANDLE_DOMAIN_IRQ menu "Machine selection" diff --git a/arch/mips/include/asm/irq_regs.h b/arch/mips/include/asm/irq_regs.h index 33bd2a06de57..8c48d6dd1d78 100644 --- a/arch/mips/include/asm/irq_regs.h +++ b/arch/mips/include/asm/irq_regs.h @@ -18,4 +18,14 @@ static inline struct pt_regs *get_irq_regs(void) return current_thread_info()->regs; } +static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) +{ + struct pt_regs *old_regs; + + old_regs = get_irq_regs(); + current_thread_info()->regs = new_regs; + + return old_regs; +} + #endif /* __ASM_IRQ_REGS_H */ -- cgit v1.2.3-59-g8ed1b From 2df11221bdc32f62ff1d8b6b945a8b19bf2a681c Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:08 -0800 Subject: MIPS: OCTEON: Add register definitions for cn73xx, cnf75xx and cn78xx. These new members of the OCTEON III family have some new registers, update some of the definitions for use in follow on patches. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12497/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/octeon/cvmx-ciu3-defs.h | 353 ++++++++++++++++++++++ arch/mips/include/asm/octeon/cvmx-fpa-defs.h | 1 + arch/mips/include/asm/octeon/cvmx-mio-defs.h | 410 +++++++++++++++++++++++++- 3 files changed, 748 insertions(+), 16 deletions(-) create mode 100644 arch/mips/include/asm/octeon/cvmx-ciu3-defs.h (limited to 'arch') diff --git a/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h b/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h new file mode 100644 index 000000000000..547f778f5b05 --- /dev/null +++ b/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2003-2016 Cavium Inc. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, but + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or + * NONINFRINGEMENT. See the GNU General Public License for more + * details. + * + */ + +#ifndef __CVMX_CIU3_DEFS_H__ +#define __CVMX_CIU3_DEFS_H__ + +#define CVMX_CIU3_FUSE CVMX_ADD_IO_SEG(0x00010100000001A0ull) +#define CVMX_CIU3_BIST CVMX_ADD_IO_SEG(0x00010100000001C0ull) +#define CVMX_CIU3_CONST CVMX_ADD_IO_SEG(0x0001010000000220ull) +#define CVMX_CIU3_CTL CVMX_ADD_IO_SEG(0x00010100000000E0ull) +#define CVMX_CIU3_DESTX_IO_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000210000ull) + ((offset) & 7) * 8) +#define CVMX_CIU3_DESTX_PP_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000200000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_GSTOP CVMX_ADD_IO_SEG(0x0001010000000140ull) +#define CVMX_CIU3_IDTX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010000110000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_IDTX_IO(offset) (CVMX_ADD_IO_SEG(0x0001010000130000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_IDTX_PPX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001010000120000ull) + ((block_id) & 255) * 0x20ull) +#define CVMX_CIU3_INTR_RAM_ECC_CTL CVMX_ADD_IO_SEG(0x0001010000000260ull) +#define CVMX_CIU3_INTR_RAM_ECC_ST CVMX_ADD_IO_SEG(0x0001010000000280ull) +#define CVMX_CIU3_INTR_READY CVMX_ADD_IO_SEG(0x00010100000002A0ull) +#define CVMX_CIU3_INTR_SLOWDOWN CVMX_ADD_IO_SEG(0x0001010000000240ull) +#define CVMX_CIU3_ISCX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010080000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_ISCX_W1C(offset) (CVMX_ADD_IO_SEG(0x0001010090000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_ISCX_W1S(offset) (CVMX_ADD_IO_SEG(0x00010100A0000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_NMI CVMX_ADD_IO_SEG(0x0001010000000160ull) +#define CVMX_CIU3_SISCX(offset) (CVMX_ADD_IO_SEG(0x0001010000220000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_TIMX(offset) (CVMX_ADD_IO_SEG(0x0001010000010000ull) + ((offset) & 15) * 8) + +union cvmx_ciu3_bist { + uint64_t u64; + struct cvmx_ciu3_bist_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_9_63 : 55; + uint64_t bist : 9; +#else + uint64_t bist : 9; + uint64_t reserved_9_63 : 55; +#endif + } s; +}; + +union cvmx_ciu3_const { + uint64_t u64; + struct cvmx_ciu3_const_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t dests_io : 16; + uint64_t pintsn : 16; + uint64_t dests_pp : 16; + uint64_t idt : 16; +#else + uint64_t idt : 16; + uint64_t dests_pp : 16; + uint64_t pintsn : 16; + uint64_t dests_io : 16; +#endif + } s; +}; + +union cvmx_ciu3_ctl { + uint64_t u64; + struct cvmx_ciu3_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_5_63 : 59; + uint64_t mcd_sel : 2; + uint64_t iscmem_le : 1; + uint64_t seq_dis : 1; + uint64_t cclk_dis : 1; +#else + uint64_t cclk_dis : 1; + uint64_t seq_dis : 1; + uint64_t iscmem_le : 1; + uint64_t mcd_sel : 2; + uint64_t reserved_5_63 : 59; +#endif + } s; +}; + +union cvmx_ciu3_destx_io_int { + uint64_t u64; + struct cvmx_ciu3_destx_io_int_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_10_31 : 22; + uint64_t intidt : 8; + uint64_t newint : 1; + uint64_t intr : 1; +#else + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t intidt : 8; + uint64_t reserved_10_31 : 22; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_destx_pp_int { + uint64_t u64; + struct cvmx_ciu3_destx_pp_int_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_10_31 : 22; + uint64_t intidt : 8; + uint64_t newint : 1; + uint64_t intr : 1; +#else + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t intidt : 8; + uint64_t reserved_10_31 : 22; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_gstop { + uint64_t u64; + struct cvmx_ciu3_gstop_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_1_63 : 63; + uint64_t gstop : 1; +#else + uint64_t gstop : 1; + uint64_t reserved_1_63 : 63; +#endif + } s; +}; + +union cvmx_ciu3_idtx_ctl { + uint64_t u64; + struct cvmx_ciu3_idtx_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_4_31 : 28; + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t ip_num : 2; +#else + uint64_t ip_num : 2; + uint64_t newint : 1; + uint64_t intr : 1; + uint64_t reserved_4_31 : 28; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_idtx_io { + uint64_t u64; + struct cvmx_ciu3_idtx_io_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_5_63 : 59; + uint64_t io : 5; +#else + uint64_t io : 5; + uint64_t reserved_5_63 : 59; +#endif + } s; +}; + +union cvmx_ciu3_idtx_ppx { + uint64_t u64; + struct cvmx_ciu3_idtx_ppx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63 : 16; + uint64_t pp : 48; +#else + uint64_t pp : 48; + uint64_t reserved_48_63 : 16; +#endif + } s; +}; + +union cvmx_ciu3_intr_ram_ecc_ctl { + uint64_t u64; + struct cvmx_ciu3_intr_ram_ecc_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_3_63 : 61; + uint64_t flip_synd : 2; + uint64_t ecc_ena : 1; +#else + uint64_t ecc_ena : 1; + uint64_t flip_synd : 2; + uint64_t reserved_3_63 : 61; +#endif + } s; +}; + +union cvmx_ciu3_intr_ram_ecc_st { + uint64_t u64; + struct cvmx_ciu3_intr_ram_ecc_st_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t addr : 20; + uint64_t reserved_6_31 : 26; + uint64_t sisc_dbe : 1; + uint64_t sisc_sbe : 1; + uint64_t idt_dbe : 1; + uint64_t idt_sbe : 1; + uint64_t isc_dbe : 1; + uint64_t isc_sbe : 1; +#else + uint64_t isc_sbe : 1; + uint64_t isc_dbe : 1; + uint64_t idt_sbe : 1; + uint64_t idt_dbe : 1; + uint64_t sisc_sbe : 1; + uint64_t sisc_dbe : 1; + uint64_t reserved_6_31 : 26; + uint64_t addr : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_intr_ready { + uint64_t u64; + struct cvmx_ciu3_intr_ready_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_46_63 : 18; + uint64_t index : 14; + uint64_t reserved_1_31 : 31; + uint64_t ready : 1; +#else + uint64_t ready : 1; + uint64_t reserved_1_31 : 31; + uint64_t index : 14; + uint64_t reserved_46_63 : 18; +#endif + } s; +}; + +union cvmx_ciu3_intr_slowdown { + uint64_t u64; + struct cvmx_ciu3_intr_slowdown_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_3_63 : 61; + uint64_t ctl : 3; +#else + uint64_t ctl : 3; + uint64_t reserved_3_63 : 61; +#endif + } s; +}; + +union cvmx_ciu3_iscx_ctl { + uint64_t u64; + struct cvmx_ciu3_iscx_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_24_63 : 40; + uint64_t idt : 8; + uint64_t imp : 1; + uint64_t reserved_2_14 : 13; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_14 : 13; + uint64_t imp : 1; + uint64_t idt : 8; + uint64_t reserved_24_63 : 40; +#endif + } s; +}; + +union cvmx_ciu3_iscx_w1c { + uint64_t u64; + struct cvmx_ciu3_iscx_w1c_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_2_63 : 62; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_63 : 62; +#endif + } s; +}; + +union cvmx_ciu3_iscx_w1s { + uint64_t u64; + struct cvmx_ciu3_iscx_w1s_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_2_63 : 62; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_63 : 62; +#endif + } s; +}; + +union cvmx_ciu3_nmi { + uint64_t u64; + struct cvmx_ciu3_nmi_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63 : 16; + uint64_t nmi : 48; +#else + uint64_t nmi : 48; + uint64_t reserved_48_63 : 16; +#endif + } s; +}; + +union cvmx_ciu3_siscx { + uint64_t u64; + struct cvmx_ciu3_siscx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t en : 64; +#else + uint64_t en : 64; +#endif + } s; +}; + +union cvmx_ciu3_timx { + uint64_t u64; + struct cvmx_ciu3_timx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_37_63 : 27; + uint64_t one_shot : 1; + uint64_t len : 36; +#else + uint64_t len : 36; + uint64_t one_shot : 1; + uint64_t reserved_37_63 : 27; +#endif + } s; +}; + +#endif diff --git a/arch/mips/include/asm/octeon/cvmx-fpa-defs.h b/arch/mips/include/asm/octeon/cvmx-fpa-defs.h index 1d79e3c7040d..887ff8e1f715 100644 --- a/arch/mips/include/asm/octeon/cvmx-fpa-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-fpa-defs.h @@ -66,6 +66,7 @@ #define CVMX_FPA_WART_CTL (CVMX_ADD_IO_SEG(0x00011800280000D8ull)) #define CVMX_FPA_WART_STATUS (CVMX_ADD_IO_SEG(0x00011800280000E0ull)) #define CVMX_FPA_WQE_THRESHOLD (CVMX_ADD_IO_SEG(0x0001180028000468ull)) +#define CVMX_FPA_CLK_COUNT (CVMX_ADD_IO_SEG(0x00012800000000F0ull)) union cvmx_fpa_addr_range_error { uint64_t u64; diff --git a/arch/mips/include/asm/octeon/cvmx-mio-defs.h b/arch/mips/include/asm/octeon/cvmx-mio-defs.h index bb0ae338a460..5196c04eee41 100644 --- a/arch/mips/include/asm/octeon/cvmx-mio-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-mio-defs.h @@ -1481,7 +1481,9 @@ union cvmx_mio_fus_dat2 { uint64_t u64; struct cvmx_mio_fus_dat2_s { #ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_48_63:16; + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; uint64_t fus118:1; uint64_t rom_info:10; uint64_t power_limit:2; @@ -1513,7 +1515,9 @@ union cvmx_mio_fus_dat2 { uint64_t power_limit:2; uint64_t rom_info:10; uint64_t fus118:1; - uint64_t reserved_48_63:16; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; #endif } s; struct cvmx_mio_fus_dat2_cn30xx { @@ -1837,50 +1841,192 @@ union cvmx_mio_fus_dat2 { #endif } cn68xx; struct cvmx_mio_fus_dat2_cn68xx cn68xxp1; + struct cvmx_mio_fus_dat2_cn70xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63:16; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_15_0:16; +#else + uint64_t reserved_15_0:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t reserved_48_63:16; +#endif + } cn70xx; + struct cvmx_mio_fus_dat2_cn70xx cn70xxp1; + struct cvmx_mio_fus_dat2_cn73xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_15_0:16; +#else + uint64_t reserved_15_0:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn73xx; + struct cvmx_mio_fus_dat2_cn78xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t reserved_48_55:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_0_15:16; +#else + uint64_t reserved_0_15:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t reserved_48_55:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn78xx; + struct cvmx_mio_fus_dat2_cn78xxp2 { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_0_15:16; +#else + uint64_t reserved_0_15:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn78xxp2; struct cvmx_mio_fus_dat2_cn61xx cnf71xx; + struct cvmx_mio_fus_dat2_cn73xx cnf75xx; }; union cvmx_mio_fus_dat3 { uint64_t u64; struct cvmx_mio_fus_dat3_s { #ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_58_63:6; + uint64_t ema0:6; uint64_t pll_ctl:10; uint64_t dfa_info_dte:3; uint64_t dfa_info_clm:4; - uint64_t reserved_40_40:1; - uint64_t ema:2; + uint64_t pll_alt_matrix:1; + uint64_t reserved_38_39:2; uint64_t efus_lck_rsv:1; uint64_t efus_lck_man:1; uint64_t pll_half_dis:1; uint64_t l2c_crip:3; - uint64_t pll_div4:1; - uint64_t reserved_29_30:2; - uint64_t bar2_en:1; + uint64_t reserved_28_31:4; uint64_t efus_lck:1; uint64_t efus_ign:1; uint64_t nozip:1; uint64_t nodfa_dte:1; - uint64_t icache:24; + uint64_t reserved_0_23:24; #else - uint64_t icache:24; + uint64_t reserved_0_23:24; uint64_t nodfa_dte:1; uint64_t nozip:1; uint64_t efus_ign:1; uint64_t efus_lck:1; - uint64_t bar2_en:1; - uint64_t reserved_29_30:2; - uint64_t pll_div4:1; + uint64_t reserved_28_31:4; uint64_t l2c_crip:3; uint64_t pll_half_dis:1; uint64_t efus_lck_man:1; uint64_t efus_lck_rsv:1; - uint64_t ema:2; - uint64_t reserved_40_40:1; + uint64_t reserved_38_39:2; + uint64_t pll_alt_matrix:1; uint64_t dfa_info_clm:4; uint64_t dfa_info_dte:3; uint64_t pll_ctl:10; - uint64_t reserved_58_63:6; + uint64_t ema0:6; #endif } s; struct cvmx_mio_fus_dat3_cn30xx { @@ -2022,7 +2168,239 @@ union cvmx_mio_fus_dat3 { struct cvmx_mio_fus_dat3_cn61xx cn66xx; struct cvmx_mio_fus_dat3_cn61xx cn68xx; struct cvmx_mio_fus_dat3_cn61xx cn68xxp1; + struct cvmx_mio_fus_dat3_cn70xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_0_17:18; +#else + uint64_t reserved_0_17:18; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn70xx; + struct cvmx_mio_fus_dat3_cn70xxp1 { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t reserved_38_40:3; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t reserved_31_31:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_0_17:18; +#else + uint64_t reserved_0_17:18; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t reserved_31_31:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t reserved_38_40:3; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn70xxp1; + struct cvmx_mio_fus_dat3_cn73xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t nohna_dte:1; + uint64_t hna_info_dte:3; + uint64_t hna_info_clm:4; + uint64_t reserved_9_9:1; + uint64_t core_pll_mul:5; + uint64_t pnr_pll_mul:4; +#else + uint64_t pnr_pll_mul:4; + uint64_t core_pll_mul:5; + uint64_t reserved_9_9:1; + uint64_t hna_info_clm:4; + uint64_t hna_info_dte:3; + uint64_t nohna_dte:1; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn73xx; + struct cvmx_mio_fus_dat3_cn78xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t reserved_38_40:3; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t reserved_31_31:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t nohna_dte:1; + uint64_t hna_info_dte:3; + uint64_t hna_info_clm:4; + uint64_t reserved_0_9:10; +#else + uint64_t reserved_0_9:10; + uint64_t hna_info_clm:4; + uint64_t hna_info_dte:3; + uint64_t nohna_dte:1; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t reserved_31_31:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t reserved_38_40:3; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn78xx; + struct cvmx_mio_fus_dat3_cn73xx cn78xxp2; struct cvmx_mio_fus_dat3_cn61xx cnf71xx; + struct cvmx_mio_fus_dat3_cnf75xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_9_17:9; + uint64_t core_pll_mul:5; + uint64_t pnr_pll_mul:4; +#else + uint64_t pnr_pll_mul:4; + uint64_t core_pll_mul:5; + uint64_t reserved_9_17:9; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cnf75xx; }; union cvmx_mio_fus_ema { -- cgit v1.2.3-59-g8ed1b From 182a6d1cd393226350ec22d973d2139adb194daa Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:09 -0800 Subject: MIPS: OCTEON: Add model checking support for cn73xx, cnf75xx and cn78xx Follow on patchs need to be able to distinguish the new models. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12498/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/octeon-model.c | 82 +++++++++++++++++++++++- arch/mips/include/asm/octeon/cvmx.h | 27 +++++++- arch/mips/include/asm/octeon/octeon-feature.h | 19 +++++- arch/mips/include/asm/octeon/octeon-model.h | 5 ++ 4 files changed, 125 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index b2104bd9ab3b..d08a2bce653c 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -71,11 +71,11 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, uint32_t fuse_data = 0; fus3.u64 = 0; - if (!OCTEON_IS_MODEL(OCTEON_CN6XXX)) + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); - num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE)); + num_cores = cvmx_octeon_num_cores(); /* Make sure the non existent devices look disabled */ switch ((chip_id >> 8) & 0xff) { @@ -121,6 +121,15 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, * later. */ switch (num_cores) { + case 48: + core_model = "90"; + break; + case 44: + core_model = "88"; + break; + case 40: + core_model = "85"; + break; case 32: core_model = "80"; break; @@ -297,7 +306,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, if (fus_dat3.s.nozip) suffix = "SCP"; - if (fus_dat3.s.bar2_en) + if (fus_dat3.cn56xx.bar2_en) suffix = "NSPB2"; } if (fus3.cn56xx.crip_1024k) @@ -369,6 +378,73 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, else suffix = "AAP"; break; + case 0x94: /* CNF71XX */ + family = "F71"; + if (fus_dat3.cnf71xx.nozip) + suffix = "SCP"; + else + suffix = "AAP"; + break; + case 0x95: /* CN78XX */ + if (num_cores == 6) /* Other core counts match generic */ + core_model = "35"; + if (OCTEON_IS_MODEL(OCTEON_CN76XX)) + family = "76"; + else + family = "78"; + if (fus_dat3.cn78xx.l2c_crip == 2) + family = "77"; + if (fus_dat3.cn78xx.nozip + && fus_dat3.cn78xx.nodfa_dte + && fus_dat3.cn78xx.nohna_dte) { + if (fus_dat3.cn78xx.nozip && + !fus_dat2.cn78xx.raid_en && + fus_dat3.cn78xx.nohna_dte) { + suffix = "CP"; + } else { + suffix = "SCP"; + } + } else if (fus_dat2.cn78xx.raid_en == 0) + suffix = "HCP"; + else + suffix = "AAP"; + break; + case 0x96: /* CN70XX */ + family = "70"; + if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32)) + family = "71"; + if (fus_dat2.cn70xx.nocrypto) + suffix = "CP"; + else if (fus_dat3.cn70xx.nodfa_dte) + suffix = "SCP"; + else + suffix = "AAP"; + break; + case 0x97: /* CN73XX */ + if (num_cores == 6) /* Other core counts match generic */ + core_model = "35"; + family = "73"; + if (fus_dat3.cn73xx.l2c_crip == 2) + family = "72"; + if (fus_dat3.cn73xx.nozip + && fus_dat3.cn73xx.nodfa_dte + && fus_dat3.cn73xx.nohna_dte) { + if (!fus_dat2.cn73xx.raid_en) + suffix = "CP"; + else + suffix = "SCP"; + } else + suffix = "AAP"; + break; + case 0x98: /* CN75XX */ + family = "F75"; + if (fus_dat3.cn78xx.nozip + && fus_dat3.cn78xx.nodfa_dte + && fus_dat3.cn78xx.nohna_dte) + suffix = "SCP"; + else + suffix = "AAP"; + break; default: family = "XX"; core_model = "XX"; diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 3e982e0c397e..2530e8731c8a 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -57,6 +57,7 @@ enum cvmx_mips_space { #include #include +#include #include #include #include @@ -341,6 +342,21 @@ static inline unsigned int cvmx_get_core_num(void) return core_num; } +/* Maximum # of bits to define core in node */ +#define CVMX_NODE_NO_SHIFT 7 +#define CVMX_NODE_MASK 0x3 +static inline unsigned int cvmx_get_node_num(void) +{ + unsigned int core_num = cvmx_get_core_num(); + + return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK; +} + +static inline unsigned int cvmx_get_local_core_num(void) +{ + return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1); +} + /** * Returns the number of bits set in the provided value. * Simple wrapper for POP instruction. @@ -448,8 +464,15 @@ static inline uint64_t cvmx_get_cycle_global(void) /* Return the number of cores available in the chip */ static inline uint32_t cvmx_octeon_num_cores(void) { - uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff; - return cvmx_pop(ciu_fuse); + u64 ciu_fuse_reg; + u64 ciu_fuse; + + if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) + ciu_fuse_reg = CVMX_CIU3_FUSE; + else + ciu_fuse_reg = CVMX_CIU_FUSE; + ciu_fuse = cvmx_read_csr(ciu_fuse_reg); + return cvmx_dpop(ciu_fuse); } #endif /* __CVMX_H__ */ diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h index 3ed10a8d7865..a19ca3b2775c 100644 --- a/arch/mips/include/asm/octeon/octeon-feature.h +++ b/arch/mips/include/asm/octeon/octeon-feature.h @@ -81,6 +81,10 @@ enum octeon_feature { OCTEON_FEATURE_HFA, OCTEON_FEATURE_DFM, OCTEON_FEATURE_CIU2, + OCTEON_FEATURE_CIU3, + /* Octeon has FPA first seen on 78XX */ + OCTEON_FEATURE_FPA3, + OCTEON_FEATURE_FAU, OCTEON_MAX_FEATURE }; @@ -110,7 +114,7 @@ static inline int octeon_has_crypto(void) * Returns Non zero if the feature exists. Zero if the feature does not * exist. */ -static inline int octeon_has_feature(enum octeon_feature feature) +static inline bool octeon_has_feature(enum octeon_feature feature) { switch (feature) { case OCTEON_FEATURE_SAAD: @@ -122,7 +126,7 @@ static inline int octeon_has_feature(enum octeon_feature feature) fus_2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); return !fus_2.s.nocrypto && !fus_2.s.nomul && fus_2.s.dorm_crypto; } else { - return 0; + return false; } case OCTEON_FEATURE_PCIE: @@ -190,11 +194,20 @@ static inline int octeon_has_feature(enum octeon_feature feature) case OCTEON_FEATURE_CIU2: return OCTEON_IS_MODEL(OCTEON_CN68XX); + case OCTEON_FEATURE_CIU3: + case OCTEON_FEATURE_FPA3: + return OCTEON_IS_MODEL(OCTEON_CN78XX) + || OCTEON_IS_MODEL(OCTEON_CNF75XX) + || OCTEON_IS_MODEL(OCTEON_CN73XX); + case OCTEON_FEATURE_FAU: + return !(OCTEON_IS_MODEL(OCTEON_CN78XX) + || OCTEON_IS_MODEL(OCTEON_CNF75XX) + || OCTEON_IS_MODEL(OCTEON_CN73XX)); default: break; } - return 0; + return false; } #endif /* __OCTEON_FEATURE_H__ */ diff --git a/arch/mips/include/asm/octeon/octeon-model.h b/arch/mips/include/asm/octeon/octeon-model.h index 92b377e36dac..6c68517c2770 100644 --- a/arch/mips/include/asm/octeon/octeon-model.h +++ b/arch/mips/include/asm/octeon/octeon-model.h @@ -74,7 +74,12 @@ * CN7XXX models with new revision encoding */ +#define OCTEON_CNF75XX_PASS1_0 0x000d9800 +#define OCTEON_CNF75XX (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_REVISION) +#define OCTEON_CNF75XX_PASS1_X (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_MINOR_REVISION) + #define OCTEON_CN73XX_PASS1_0 0x000d9700 +#define OCTEON_CN73XX_PASS1_1 0x000d9701 #define OCTEON_CN73XX (OCTEON_CN73XX_PASS1_0 | OM_IGNORE_REVISION) #define OCTEON_CN73XX_PASS1_X (OCTEON_CN73XX_PASS1_0 | \ OM_IGNORE_MINOR_REVISION) -- cgit v1.2.3-59-g8ed1b From 9bc22239956e3877d085b843bfe89ab2a98ab50a Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:10 -0800 Subject: MIPS: OCTEON: Don't attempt to use nonexistent registers on OCTEON III models. Attempts to read the nonexistent registers results in bus errors. Either use registers that exist, or don't do the access as appropriate. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12502/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/csrc-octeon.c | 13 +++++++++---- arch/mips/cavium-octeon/setup.c | 34 +++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c index 1882e6475dd0..23c2344a3552 100644 --- a/arch/mips/cavium-octeon/csrc-octeon.c +++ b/arch/mips/cavium-octeon/csrc-octeon.c @@ -19,6 +19,7 @@ #include #include #include +#include static u64 f; static u64 rdiv; @@ -65,9 +66,13 @@ void __init octeon_setup_delays(void) */ void octeon_init_cvmcount(void) { + u64 clk_reg; unsigned long flags; unsigned loops = 2; + clk_reg = octeon_has_feature(OCTEON_FEATURE_FPA3) ? + CVMX_FPA_CLK_COUNT : CVMX_IPD_CLK_COUNT; + /* Clobber loops so GCC will not unroll the following while loop. */ asm("" : "+r" (loops)); @@ -77,18 +82,18 @@ void octeon_init_cvmcount(void) * which should give more deterministic timing. */ while (loops--) { - u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT); + u64 clk_count = cvmx_read_csr(clk_reg); if (rdiv != 0) { - ipd_clk_count *= rdiv; + clk_count *= rdiv; if (f != 0) { asm("dmultu\t%[cnt],%[f]\n\t" "mfhi\t%[cnt]" - : [cnt] "+r" (ipd_clk_count) + : [cnt] "+r" (clk_count) : [f] "r" (f) : "hi", "lo"); } } - write_c0_cvmcount(ipd_clk_count); + write_c0_cvmcount(clk_count); } local_irq_restore(flags); } diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 9c6ad2fab344..54a214ec33d3 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -492,8 +492,6 @@ const char *get_system_type(void) void octeon_user_io_init(void) { union octeon_cvmemctl cvmmemctl; - union cvmx_iob_fau_timeout fau_timeout; - union cvmx_pow_nw_tim nm_tim; /* Get the current settings for CP0_CVMMEMCTL_REG */ cvmmemctl.u64 = read_c0_cvmmemctl(); @@ -595,17 +593,27 @@ void octeon_user_io_init(void) CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128); - /* Set a default for the hardware timeouts */ - fau_timeout.u64 = 0; - fau_timeout.s.tout_val = 0xfff; - /* Disable tagwait FAU timeout */ - fau_timeout.s.tout_enb = 0; - cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64); - - nm_tim.u64 = 0; - /* 4096 cycles */ - nm_tim.s.nw_tim = 3; - cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64); + if (octeon_has_feature(OCTEON_FEATURE_FAU)) { + union cvmx_iob_fau_timeout fau_timeout; + + /* Set a default for the hardware timeouts */ + fau_timeout.u64 = 0; + fau_timeout.s.tout_val = 0xfff; + /* Disable tagwait FAU timeout */ + fau_timeout.s.tout_enb = 0; + cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64); + } + + if ((!OCTEON_IS_MODEL(OCTEON_CN68XX) && + !OCTEON_IS_MODEL(OCTEON_CN7XXX)) || + OCTEON_IS_MODEL(OCTEON_CN70XX)) { + union cvmx_pow_nw_tim nm_tim; + + nm_tim.u64 = 0; + /* 4096 cycles */ + nm_tim.s.nw_tim = 3; + cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64); + } write_octeon_c0_icacheerr(0); write_c0_derraddr1(0); -- cgit v1.2.3-59-g8ed1b From ce210d35bb93c2c5c8857878123275ecdcfd7018 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:11 -0800 Subject: MIPS: OCTEON: Add support for OCTEON III interrupt controller. Add irq_chip support for both IPI and "normal" interrupts of the CIU3 controller. Document the device tree binding for the CIU3. Some functions are non-static as they will be used by follow-on support for MSI-X. Signed-off-by: David Daney Acked-by: Rob Herring Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala Cc: devicetree@vger.kernel.org Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12500/ Signed-off-by: Ralf Baechle --- .../devicetree/bindings/mips/cavium/ciu3.txt | 27 + arch/mips/cavium-octeon/octeon-irq.c | 650 ++++++++++++++++++++- arch/mips/include/asm/octeon/octeon.h | 19 + 3 files changed, 695 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu3.txt (limited to 'arch') diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu3.txt b/Documentation/devicetree/bindings/mips/cavium/ciu3.txt new file mode 100644 index 000000000000..616862ad2b71 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/ciu3.txt @@ -0,0 +1,27 @@ +* Central Interrupt Unit v3 + +Properties: +- compatible: "cavium,octeon-7890-ciu3" + + Compatibility with 78XX and 73XX SOCs. + +- interrupt-controller: This is an interrupt controller. + +- reg: The base address of the CIU's register bank. + +- #interrupt-cells: Must be <2>. The first cell is source number. + The second cell indicates the triggering semantics, and may have a + value of either 4 for level semantics, or 1 for edge semantics. + +Example: + interrupt-controller@1010000000000 { + compatible = "cavium,octeon-7890-ciu3"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Source number (20 significant bits) + * 2) Trigger type: (4 == level, 1 == edge) + */ + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x10100 0x00000000 0x0 0xb0000000>; + }; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index bc30d3a90b2f..9b6a65b959f9 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -19,15 +19,52 @@ #include #include +#include static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror); static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror); static DEFINE_PER_CPU(raw_spinlock_t, octeon_irq_ciu_spinlock); +static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip2); + +static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip3); +static DEFINE_PER_CPU(struct octeon_ciu3_info *, octeon_ciu3_info); +#define CIU3_MBOX_PER_CORE 10 + +/* + * The 8 most significant bits of the intsn identify the interrupt major block. + * Each major block might use its own interrupt domain. Thus 256 domains are + * needed. + */ +#define MAX_CIU3_DOMAINS 256 + +typedef irq_hw_number_t (*octeon_ciu3_intsn2hw_t)(struct irq_domain *, unsigned int); + +/* Information for each ciu3 in the system */ +struct octeon_ciu3_info { + u64 ciu3_addr; + int node; + struct irq_domain *domain[MAX_CIU3_DOMAINS]; + octeon_ciu3_intsn2hw_t intsn2hw[MAX_CIU3_DOMAINS]; +}; + +/* Each ciu3 in the system uses its own data (one ciu3 per node) */ +static struct octeon_ciu3_info *octeon_ciu3_info_per_node[4]; struct octeon_irq_ciu_domain_data { int num_sum; /* number of sum registers (2 or 3). */ }; +/* Register offsets from ciu3_addr */ +#define CIU3_CONST 0x220 +#define CIU3_IDT_CTL(_idt) ((_idt) * 8 + 0x110000) +#define CIU3_IDT_PP(_idt, _idx) ((_idt) * 32 + (_idx) * 8 + 0x120000) +#define CIU3_IDT_IO(_idt) ((_idt) * 8 + 0x130000) +#define CIU3_DEST_PP_INT(_pp_ip) ((_pp_ip) * 8 + 0x200000) +#define CIU3_DEST_IO_INT(_io) ((_io) * 8 + 0x210000) +#define CIU3_ISC_CTL(_intsn) ((_intsn) * 8 + 0x80000000) +#define CIU3_ISC_W1C(_intsn) ((_intsn) * 8 + 0x90000000) +#define CIU3_ISC_W1S(_intsn) ((_intsn) * 8 + 0xa0000000) + static __read_mostly int octeon_irq_ciu_to_irq[8][64]; struct octeon_ciu_chip_data { @@ -39,10 +76,11 @@ struct octeon_ciu_chip_data { struct { /* only used for ciu/ciu2 */ u8 line; u8 bit; - u8 gpio_line; }; }; + int gpio_line; int current_cpu; /* Next CPU expected to take this irq */ + int ciu_node; /* NUMA node number of the CIU */ }; struct octeon_core_chip_data { @@ -626,6 +664,18 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) } } +static int octeon_irq_ciu_set_type(struct irq_data *data, unsigned int t) +{ + irqd_set_trigger_type(data, t); + + if (t & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(data, handle_edge_irq); + else + irq_set_handler_locked(data, handle_level_irq); + + return IRQ_SET_MASK_OK; +} + static void octeon_irq_gpio_setup(struct irq_data *data) { union cvmx_gpio_bit_cfgx cfg; @@ -863,6 +913,16 @@ static int octeon_irq_ciu_set_affinity_sum2(struct irq_data *data, } #endif +static unsigned int edge_startup(struct irq_data *data) +{ + /* ack any pending edge-irq at startup, so there is + * an _edge_ to fire on when the event reappears. + */ + data->chip->irq_ack(data); + data->chip->irq_enable(data); + return 0; +} + /* * Newer octeon chips have support for lockless CIU operation. */ @@ -2271,10 +2331,598 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, return 0; } +int octeon_irq_ciu3_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + struct octeon_ciu3_info *ciu3_info = d->host_data; + unsigned int hwirq, type, intsn_major; + union cvmx_ciu3_iscx_ctl isc; + + if (intsize < 2) + return -EINVAL; + hwirq = intspec[0]; + type = intspec[1]; + + if (hwirq >= (1 << 20)) + return -EINVAL; + + intsn_major = hwirq >> 12; + switch (intsn_major) { + case 0x04: /* Software handled separately. */ + return -EINVAL; + default: + break; + } + + isc.u64 = cvmx_read_csr(ciu3_info->ciu3_addr + CIU3_ISC_CTL(hwirq)); + if (!isc.s.imp) + return -EINVAL; + + switch (type) { + case 4: /* official value for level triggering. */ + *out_type = IRQ_TYPE_LEVEL_HIGH; + break; + case 0: /* unofficial value, but we might as well let it work. */ + case 1: /* official value for edge triggering. */ + *out_type = IRQ_TYPE_EDGE_RISING; + break; + default: /* Nothing else is acceptable. */ + return -EINVAL; + } + + *out_hwirq = hwirq; + + return 0; +} + +void octeon_irq_ciu3_enable(struct irq_data *data) +{ + int cpu; + union cvmx_ciu3_iscx_ctl isc_ctl; + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_ctl_addr; + + struct octeon_ciu_chip_data *cd; + + cpu = next_cpu_for_irq(data); + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu); + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + cvmx_read_csr(isc_ctl_addr); +} + +void octeon_irq_ciu3_disable(struct irq_data *data) +{ + u64 isc_ctl_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + + struct octeon_ciu_chip_data *cd; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + cvmx_write_csr(isc_ctl_addr, 0); + cvmx_read_csr(isc_ctl_addr); +} + +void octeon_irq_ciu3_ack(struct irq_data *data) +{ + u64 isc_w1c_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + struct octeon_ciu_chip_data *cd; + u32 trigger_type = irqd_get_trigger_type(data); + + /* + * We use a single irq_chip, so we have to do nothing to ack a + * level interrupt. + */ + if (!(trigger_type & IRQ_TYPE_EDGE_BOTH)) + return; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.raw = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +void octeon_irq_ciu3_mask(struct irq_data *data) +{ + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr; + struct octeon_ciu_chip_data *cd; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +void octeon_irq_ciu3_mask_ack(struct irq_data *data) +{ + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr; + struct octeon_ciu_chip_data *cd; + u32 trigger_type = irqd_get_trigger_type(data); + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + /* + * We use a single irq_chip, so only ack an edge (!level) + * interrupt. + */ + if (trigger_type & IRQ_TYPE_EDGE_BOTH) + isc_w1c.s.raw = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +#ifdef CONFIG_SMP +int octeon_irq_ciu3_set_affinity(struct irq_data *data, + const struct cpumask *dest, bool force) +{ + union cvmx_ciu3_iscx_ctl isc_ctl; + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_ctl_addr; + int cpu; + bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data); + struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data); + + if (!cpumask_subset(dest, cpumask_of_node(cd->ciu_node))) + return -EINVAL; + + if (!enable_one) + return IRQ_SET_MASK_OK; + + cd = irq_data_get_irq_chip_data(data); + cpu = cpumask_first(dest); + if (cpu >= nr_cpu_ids) + cpu = smp_processor_id(); + cd->current_cpu = cpu; + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu); + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + cvmx_read_csr(isc_ctl_addr); + + return IRQ_SET_MASK_OK; +} +#endif + +static struct irq_chip octeon_irq_chip_ciu3 = { + .name = "CIU3", + .irq_startup = edge_startup, + .irq_enable = octeon_irq_ciu3_enable, + .irq_disable = octeon_irq_ciu3_disable, + .irq_ack = octeon_irq_ciu3_ack, + .irq_mask = octeon_irq_ciu3_mask, + .irq_mask_ack = octeon_irq_ciu3_mask_ack, + .irq_unmask = octeon_irq_ciu3_enable, + .irq_set_type = octeon_irq_ciu_set_type, +#ifdef CONFIG_SMP + .irq_set_affinity = octeon_irq_ciu3_set_affinity, + .irq_cpu_offline = octeon_irq_cpu_offline_ciu, +#endif +}; + +int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw, struct irq_chip *chip) +{ + struct octeon_ciu3_info *ciu3_info = d->host_data; + struct octeon_ciu_chip_data *cd = kzalloc_node(sizeof(*cd), GFP_KERNEL, + ciu3_info->node); + if (!cd) + return -ENOMEM; + cd->intsn = hw; + cd->current_cpu = -1; + cd->ciu3_addr = ciu3_info->ciu3_addr; + cd->ciu_node = ciu3_info->node; + irq_set_chip_and_handler(virq, chip, handle_edge_irq); + irq_set_chip_data(virq, cd); + + return 0; +} + +static int octeon_irq_ciu3_map(struct irq_domain *d, + unsigned int virq, irq_hw_number_t hw) +{ + return octeon_irq_ciu3_mapx(d, virq, hw, &octeon_irq_chip_ciu3); +} + +static struct irq_domain_ops octeon_dflt_domain_ciu3_ops = { + .map = octeon_irq_ciu3_map, + .unmap = octeon_irq_free_cd, + .xlate = octeon_irq_ciu3_xlat, +}; + +static void octeon_irq_ciu3_ip2(void) +{ + union cvmx_ciu3_destx_pp_int dest_pp_int; + struct octeon_ciu3_info *ciu3_info; + u64 ciu3_addr; + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + ciu3_addr = ciu3_info->ciu3_addr; + + dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(3 * cvmx_get_local_core_num())); + + if (likely(dest_pp_int.s.intr)) { + irq_hw_number_t intsn = dest_pp_int.s.intsn; + irq_hw_number_t hw; + struct irq_domain *domain; + /* Get the domain to use from the major block */ + int block = intsn >> 12; + int ret; + + domain = ciu3_info->domain[block]; + if (ciu3_info->intsn2hw[block]) + hw = ciu3_info->intsn2hw[block](domain, intsn); + else + hw = intsn; + + ret = handle_domain_irq(domain, hw, NULL); + if (ret < 0) { + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); + spurious_interrupt(); + } + } else { + spurious_interrupt(); + } +} + +/* + * 10 mbox per core starting from zero. + * Base mbox is core * 10 + */ +static unsigned int octeon_irq_ciu3_base_mbox_intsn(int core) +{ + /* SW (mbox) are 0x04 in bits 12..19 */ + return 0x04000 + CIU3_MBOX_PER_CORE * core; +} + +static unsigned int octeon_irq_ciu3_mbox_intsn_for_core(int core, unsigned int mbox) +{ + return octeon_irq_ciu3_base_mbox_intsn(core) + mbox; +} + +static unsigned int octeon_irq_ciu3_mbox_intsn_for_cpu(int cpu, unsigned int mbox) +{ + int local_core = octeon_coreid_for_cpu(cpu) & 0x3f; + + return octeon_irq_ciu3_mbox_intsn_for_core(local_core, mbox); +} + +static void octeon_irq_ciu3_mbox(void) +{ + union cvmx_ciu3_destx_pp_int dest_pp_int; + struct octeon_ciu3_info *ciu3_info; + u64 ciu3_addr; + int core = cvmx_get_local_core_num(); + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + ciu3_addr = ciu3_info->ciu3_addr; + + dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(1 + 3 * core)); + + if (likely(dest_pp_int.s.intr)) { + irq_hw_number_t intsn = dest_pp_int.s.intsn; + int mbox = intsn - octeon_irq_ciu3_base_mbox_intsn(core); + + if (likely(mbox >= 0 && mbox < CIU3_MBOX_PER_CORE)) { + do_IRQ(mbox + OCTEON_IRQ_MBOX0); + } else { + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); + spurious_interrupt(); + } + } else { + spurious_interrupt(); + } +} + +void octeon_ciu3_mbox_send(int cpu, unsigned int mbox) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + union cvmx_ciu3_iscx_w1s isc_w1s; + u64 isc_w1s_addr; + + if (WARN_ON_ONCE(mbox >= CIU3_MBOX_PER_CORE)) + return; + + intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox); + ciu3_info = per_cpu(octeon_ciu3_info, cpu); + isc_w1s_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1S(intsn); + + isc_w1s.u64 = 0; + isc_w1s.s.raw = 1; + + cvmx_write_csr(isc_w1s_addr, isc_w1s.u64); + cvmx_read_csr(isc_w1s_addr); +} + +static void octeon_irq_ciu3_mbox_set_enable(struct irq_data *data, int cpu, bool en) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + u64 isc_ctl_addr, isc_w1c_addr; + union cvmx_ciu3_iscx_ctl isc_ctl; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox); + ciu3_info = per_cpu(octeon_ciu3_info, cpu); + isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn); + isc_ctl_addr = ciu3_info->ciu3_addr + CIU3_ISC_CTL(intsn); + + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + + cvmx_write_csr(isc_w1c_addr, isc_ctl.u64); + cvmx_write_csr(isc_ctl_addr, 0); + if (en) { + unsigned int idt = per_cpu(octeon_irq_ciu3_idt_ip3, cpu); + + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = idt; + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + } + cvmx_read_csr(isc_ctl_addr); +} + +static void octeon_irq_ciu3_mbox_enable(struct irq_data *data) +{ + int cpu; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + WARN_ON(mbox >= CIU3_MBOX_PER_CORE); + + for_each_online_cpu(cpu) + octeon_irq_ciu3_mbox_set_enable(data, cpu, true); +} + +static void octeon_irq_ciu3_mbox_disable(struct irq_data *data) +{ + int cpu; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + WARN_ON(mbox >= CIU3_MBOX_PER_CORE); + + for_each_online_cpu(cpu) + octeon_irq_ciu3_mbox_set_enable(data, cpu, false); +} + +static void octeon_irq_ciu3_mbox_ack(struct irq_data *data) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + u64 isc_w1c_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + intsn = octeon_irq_ciu3_mbox_intsn_for_core(cvmx_get_local_core_num(), mbox); + + isc_w1c.u64 = 0; + isc_w1c.s.raw = 1; + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +static void octeon_irq_ciu3_mbox_cpu_online(struct irq_data *data) +{ + octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), true); +} + +static void octeon_irq_ciu3_mbox_cpu_offline(struct irq_data *data) +{ + octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), false); +} + +static int octeon_irq_ciu3_alloc_resources(struct octeon_ciu3_info *ciu3_info) +{ + u64 b = ciu3_info->ciu3_addr; + int idt_ip2, idt_ip3, idt_ip4; + int unused_idt2; + int core = cvmx_get_local_core_num(); + int i; + + __this_cpu_write(octeon_ciu3_info, ciu3_info); + + /* + * 4 idt per core starting from 1 because zero is reserved. + * Base idt per core is 4 * core + 1 + */ + idt_ip2 = core * 4 + 1; + idt_ip3 = core * 4 + 2; + idt_ip4 = core * 4 + 3; + unused_idt2 = core * 4 + 4; + __this_cpu_write(octeon_irq_ciu3_idt_ip2, idt_ip2); + __this_cpu_write(octeon_irq_ciu3_idt_ip3, idt_ip3); + + /* ip2 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip2), 0); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip2, 0), 1ull << core); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip2), 0); + + /* ip3 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip3), 1); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip3, 0), 1ull << core); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip3), 0); + + /* ip4 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip4), 2); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip4, 0), 0); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip4), 0); + + cvmx_write_csr(b + CIU3_IDT_CTL(unused_idt2), 0); + cvmx_write_csr(b + CIU3_IDT_PP(unused_idt2, 0), 0); + cvmx_write_csr(b + CIU3_IDT_IO(unused_idt2), 0); + + for (i = 0; i < CIU3_MBOX_PER_CORE; i++) { + unsigned int intsn = octeon_irq_ciu3_mbox_intsn_for_core(core, i); + + cvmx_write_csr(b + CIU3_ISC_W1C(intsn), 2); + cvmx_write_csr(b + CIU3_ISC_CTL(intsn), 0); + } + + return 0; +} + +static void octeon_irq_setup_secondary_ciu3(void) +{ + struct octeon_ciu3_info *ciu3_info; + + ciu3_info = octeon_ciu3_info_per_node[cvmx_get_node_num()]; + octeon_irq_ciu3_alloc_resources(ciu3_info); + irq_cpu_online(); + + /* Enable the CIU lines */ + set_c0_status(STATUSF_IP3 | STATUSF_IP2); + if (octeon_irq_use_ip4) + set_c0_status(STATUSF_IP4); + else + clear_c0_status(STATUSF_IP4); +} + +static struct irq_chip octeon_irq_chip_ciu3_mbox = { + .name = "CIU3-M", + .irq_enable = octeon_irq_ciu3_mbox_enable, + .irq_disable = octeon_irq_ciu3_mbox_disable, + .irq_ack = octeon_irq_ciu3_mbox_ack, + + .irq_cpu_online = octeon_irq_ciu3_mbox_cpu_online, + .irq_cpu_offline = octeon_irq_ciu3_mbox_cpu_offline, + .flags = IRQCHIP_ONOFFLINE_ENABLED, +}; + +static int __init octeon_irq_init_ciu3(struct device_node *ciu_node, + struct device_node *parent) +{ + int i; + int node; + struct irq_domain *domain; + struct octeon_ciu3_info *ciu3_info; + const __be32 *zero_addr; + u64 base_addr; + union cvmx_ciu3_const consts; + + node = 0; /* of_node_to_nid(ciu_node); */ + ciu3_info = kzalloc_node(sizeof(*ciu3_info), GFP_KERNEL, node); + + if (!ciu3_info) + return -ENOMEM; + + zero_addr = of_get_address(ciu_node, 0, NULL, NULL); + if (WARN_ON(!zero_addr)) + return -EINVAL; + + base_addr = of_translate_address(ciu_node, zero_addr); + base_addr = (u64)phys_to_virt(base_addr); + + ciu3_info->ciu3_addr = base_addr; + ciu3_info->node = node; + + consts.u64 = cvmx_read_csr(base_addr + CIU3_CONST); + + octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu3; + + octeon_irq_ip2 = octeon_irq_ciu3_ip2; + octeon_irq_ip3 = octeon_irq_ciu3_mbox; + octeon_irq_ip4 = octeon_irq_ip4_mask; + + if (node == cvmx_get_node_num()) { + /* Mips internal */ + octeon_irq_init_core(); + + /* Only do per CPU things if it is the CIU of the boot node. */ + i = irq_alloc_descs_from(OCTEON_IRQ_MBOX0, 8, node); + WARN_ON(i < 0); + + for (i = 0; i < 8; i++) + irq_set_chip_and_handler(i + OCTEON_IRQ_MBOX0, + &octeon_irq_chip_ciu3_mbox, handle_percpu_irq); + } + + /* + * Initialize all domains to use the default domain. Specific major + * blocks will overwrite the default domain as needed. + */ + domain = irq_domain_add_tree(ciu_node, &octeon_dflt_domain_ciu3_ops, + ciu3_info); + for (i = 0; i < MAX_CIU3_DOMAINS; i++) + ciu3_info->domain[i] = domain; + + octeon_ciu3_info_per_node[node] = ciu3_info; + + if (node == cvmx_get_node_num()) { + /* Only do per CPU things if it is the CIU of the boot node. */ + octeon_irq_ciu3_alloc_resources(ciu3_info); + if (node == 0) + irq_set_default_host(domain); + + octeon_irq_use_ip4 = false; + /* Enable the CIU lines */ + set_c0_status(STATUSF_IP2 | STATUSF_IP3); + clear_c0_status(STATUSF_IP4); + } + + return 0; +} + static struct of_device_id ciu_types[] __initdata = { {.compatible = "cavium,octeon-3860-ciu", .data = octeon_irq_init_ciu}, {.compatible = "cavium,octeon-3860-gpio", .data = octeon_irq_init_gpio}, {.compatible = "cavium,octeon-6880-ciu2", .data = octeon_irq_init_ciu2}, + {.compatible = "cavium,octeon-7890-ciu3", .data = octeon_irq_init_ciu3}, {.compatible = "cavium,octeon-7130-cib", .data = octeon_irq_init_cib}, {} }; diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index de9f74ee5dd0..53d51aeb9140 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -299,6 +299,25 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val) cvmx_read64_uint32(address ^ 4); } +struct irq_domain; +struct device_node; +struct irq_data; +struct irq_chip; +void octeon_ciu3_mbox_send(int cpu, unsigned int mbox); +int octeon_irq_ciu3_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type); +void octeon_irq_ciu3_enable(struct irq_data *data); +void octeon_irq_ciu3_disable(struct irq_data *data); +void octeon_irq_ciu3_ack(struct irq_data *data); +void octeon_irq_ciu3_mask(struct irq_data *data); +void octeon_irq_ciu3_mask_ack(struct irq_data *data); +int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw, struct irq_chip *chip); + /* Octeon multiplier save/restore routines from octeon_switch.S */ void octeon_mult_save(void); void octeon_mult_restore(void); -- cgit v1.2.3-59-g8ed1b From c6d2b22eb5211e96e932428bc1183c6ad57d5e54 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:12 -0800 Subject: MIPS: OCTEON: Add SMP support for OCTEON cn78xx et al. OCTEON chips with the CIU3 interrupt controller use a different IPI mechanism that previous models. Add plat_smp_ops for the cn78xx and probing code to choose between the two types of ops. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12499/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 4 +- arch/mips/cavium-octeon/smp.c | 145 +++++++++++++++++++++++++++++++--- arch/mips/include/asm/octeon/octeon.h | 6 ++ 3 files changed, 139 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 54a214ec33d3..8ffc1f108239 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -43,8 +43,6 @@ #include #include -extern struct plat_smp_ops octeon_smp_ops; - #ifdef CONFIG_PCI extern void pci_console_init(const char *arg); #endif @@ -888,7 +886,7 @@ void __init prom_init(void) #endif octeon_user_io_init(); - register_smp_ops(&octeon_smp_ops); + octeon_setup_smp(); } /* Exclude a single page from the regions obtained in plat_mem_setup. */ diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 42395c561aa5..32c0cce73ed7 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -30,25 +30,55 @@ uint64_t octeon_bootloader_entry_addr; EXPORT_SYMBOL(octeon_bootloader_entry_addr); #endif +static void octeon_icache_flush(void) +{ + asm volatile ("synci 0($0)\n"); +} + +static void (*octeon_message_functions[8])(void) = { + scheduler_ipi, + generic_smp_call_function_interrupt, + octeon_icache_flush, +}; + static irqreturn_t mailbox_interrupt(int irq, void *dev_id) { - const int coreid = cvmx_get_core_num(); - uint64_t action; + u64 mbox_clrx = CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()); + u64 action; + int i; + + /* + * Make sure the function array initialization remains + * correct. + */ + BUILD_BUG_ON(SMP_RESCHEDULE_YOURSELF != (1 << 0)); + BUILD_BUG_ON(SMP_CALL_FUNCTION != (1 << 1)); + BUILD_BUG_ON(SMP_ICACHE_FLUSH != (1 << 2)); + + /* + * Load the mailbox register to figure out what we're supposed + * to do. + */ + action = cvmx_read_csr(mbox_clrx); - /* Load the mailbox register to figure out what we're supposed to do */ - action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)) & 0xffff; + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + action &= 0xff; + else + action &= 0xffff; /* Clear the mailbox to clear the interrupt */ - cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action); + cvmx_write_csr(mbox_clrx, action); - if (action & SMP_CALL_FUNCTION) - generic_smp_call_function_interrupt(); - if (action & SMP_RESCHEDULE_YOURSELF) - scheduler_ipi(); + for (i = 0; i < ARRAY_SIZE(octeon_message_functions) && action;) { + if (action & 1) { + void (*fn)(void) = octeon_message_functions[i]; - /* Check if we've been told to flush the icache */ - if (action & SMP_ICACHE_FLUSH) - asm volatile ("synci 0($0)\n"); + if (fn) + fn(); + } + action >>= 1; + i++; + } return IRQ_HANDLED; } @@ -102,10 +132,10 @@ static void octeon_smp_setup(void) const int coreid = cvmx_get_core_num(); int cpus; int id; - int core_mask = octeon_get_boot_coremask(); struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get(); #ifdef CONFIG_HOTPLUG_CPU + int core_mask = octeon_get_boot_coremask(); unsigned int num_cores = cvmx_octeon_num_cores(); #endif @@ -390,3 +420,92 @@ struct plat_smp_ops octeon_smp_ops = { .cpu_die = octeon_cpu_die, #endif }; + +static irqreturn_t octeon_78xx_reched_interrupt(int irq, void *dev_id) +{ + scheduler_ipi(); + return IRQ_HANDLED; +} + +static irqreturn_t octeon_78xx_call_function_interrupt(int irq, void *dev_id) +{ + generic_smp_call_function_interrupt(); + return IRQ_HANDLED; +} + +static irqreturn_t octeon_78xx_icache_flush_interrupt(int irq, void *dev_id) +{ + octeon_icache_flush(); + return IRQ_HANDLED; +} + +/* + * Callout to firmware before smp_init + */ +static void octeon_78xx_prepare_cpus(unsigned int max_cpus) +{ + if (request_irq(OCTEON_IRQ_MBOX0 + 0, + octeon_78xx_reched_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler", + octeon_78xx_reched_interrupt)) { + panic("Cannot request_irq for SchedulerIPI"); + } + if (request_irq(OCTEON_IRQ_MBOX0 + 1, + octeon_78xx_call_function_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call", + octeon_78xx_call_function_interrupt)) { + panic("Cannot request_irq for SMP-Call"); + } + if (request_irq(OCTEON_IRQ_MBOX0 + 2, + octeon_78xx_icache_flush_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "ICache-Flush", + octeon_78xx_icache_flush_interrupt)) { + panic("Cannot request_irq for ICache-Flush"); + } +} + +static void octeon_78xx_send_ipi_single(int cpu, unsigned int action) +{ + int i; + + for (i = 0; i < 8; i++) { + if (action & 1) + octeon_ciu3_mbox_send(cpu, i); + action >>= 1; + } +} + +static void octeon_78xx_send_ipi_mask(const struct cpumask *mask, + unsigned int action) +{ + unsigned int cpu; + + for_each_cpu(cpu, mask) + octeon_78xx_send_ipi_single(cpu, action); +} + +static struct plat_smp_ops octeon_78xx_smp_ops = { + .send_ipi_single = octeon_78xx_send_ipi_single, + .send_ipi_mask = octeon_78xx_send_ipi_mask, + .init_secondary = octeon_init_secondary, + .smp_finish = octeon_smp_finish, + .boot_secondary = octeon_boot_secondary, + .smp_setup = octeon_smp_setup, + .prepare_cpus = octeon_78xx_prepare_cpus, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = octeon_cpu_disable, + .cpu_die = octeon_cpu_die, +#endif +}; + +void __init octeon_setup_smp(void) +{ + struct plat_smp_ops *ops; + + if (octeon_has_feature(OCTEON_FEATURE_CIU3)) + ops = &octeon_78xx_smp_ops; + else + ops = &octeon_smp_ops; + + register_smp_ops(ops); +} diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index 53d51aeb9140..07c0516ef4d5 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -299,6 +299,12 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val) cvmx_read64_uint32(address ^ 4); } +#ifdef CONFIG_SMP +void octeon_setup_smp(void); +#else +static inline void octeon_setup_smp(void) {} +#endif + struct irq_domain; struct device_node; struct irq_data; -- cgit v1.2.3-59-g8ed1b From 490f7548cfce36b63ec517a8ff7382287db86c29 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:13 -0800 Subject: MIPS: OCTEON: Simplify code in octeon_irq_ciu_gpio_set_type() Use the trigger type passed in to the function instead of reading it back out of the irq_data. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12501/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 9b6a65b959f9..368eb490354c 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -713,7 +713,7 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t) irqd_set_trigger_type(data, t); octeon_irq_gpio_setup(data); - if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH) + if (t & IRQ_TYPE_EDGE_BOTH) irq_set_handler_locked(data, handle_edge_irq); else irq_set_handler_locked(data, handle_level_irq); -- cgit v1.2.3-59-g8ed1b From 6ecffafe242ec6d2789631499452c54177f0bb4c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 23 Feb 2016 00:22:55 +0200 Subject: MIPS: Octeon: board_type_to_string: return NULL for unsupported board Return NULL for unsupported board. Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12581/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 9 +++++++-- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 8ffc1f108239..4759494c3ff4 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -466,9 +466,14 @@ static char __read_mostly octeon_system_type[80]; static int __init init_octeon_system_type(void) { + char const *board_type; + + board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type); + if (board_type == NULL) + board_type = "Unsupported Board"; + snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", - cvmx_board_type_to_string(octeon_bootinfo->board_type), - octeon_model_get_string(read_c0_prid())); + board_type, octeon_model_get_string(read_c0_prid())); return 0; } diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index c455d34f5a4f..62787765575e 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -400,7 +400,7 @@ static inline const char *cvmx_board_type_to_string(enum ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX) } - return "Unsupported Board"; + return NULL; } #define ENUM_CHIP_TYPE_CASE(x) \ -- cgit v1.2.3-59-g8ed1b From 8f2068bc9e875540b5fb372294095833651ea1e2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 23 Feb 2016 00:22:56 +0200 Subject: MIPS: Octeon: Initialize system type string after device tree init. Initialize system type string after device tree init. Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12583/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 4759494c3ff4..09a83cd6bfe8 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -464,7 +464,7 @@ static void octeon_halt(void) static char __read_mostly octeon_system_type[80]; -static int __init init_octeon_system_type(void) +static void __init init_octeon_system_type(void) { char const *board_type; @@ -474,10 +474,7 @@ static int __init init_octeon_system_type(void) snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", board_type, octeon_model_get_string(read_c0_prid())); - - return 0; } -early_initcall(init_octeon_system_type); /** * Return a string representing the system type @@ -1141,6 +1138,7 @@ void __init device_tree_init(void) pr_info("Using internal Device Tree.\n"); } unflatten_and_copy_device_tree(); + init_octeon_system_type(); } static int __initdata disable_octeon_edac_p; -- cgit v1.2.3-59-g8ed1b From 1a1590ab1a4a0898fe0a6809e5bcd7c225e3b4d6 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 23 Feb 2016 00:22:57 +0200 Subject: MIPS: Octeon: Use model string from DTB for unknown board type Use model string from DTB for board type if the board is unknown. This is more informative, e.g. with EdgeRouter Pro the /proc/cpuinfo will display "ubnt,e200 (CN6120p1.1-1000-NSP)" instead of misleading "Unsupported Board". Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12582/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 09a83cd6bfe8..37ac229bebb6 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -469,8 +469,16 @@ static void __init init_octeon_system_type(void) char const *board_type; board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type); - if (board_type == NULL) - board_type = "Unsupported Board"; + if (board_type == NULL) { + struct device_node *root; + int ret; + + root = of_find_node_by_path("/"); + ret = of_property_read_string(root, "model", &board_type); + of_node_put(root); + if (ret) + board_type = "Unsupported Board"; + } snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", board_type, octeon_model_get_string(read_c0_prid())); -- cgit v1.2.3-59-g8ed1b From 43349b9e4bb008a2fb7e92de53fe2aa1ccf8ea24 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 24 Feb 2016 00:52:05 +0200 Subject: MIPS: Octeon: device_tree_init: use separate pass to fill mac addresses Use separate pass to fill MAC addresses. This is needed because we want to do this also for the appended DTB. Signed-off-by: Aaro Koskinen Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12588/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 86 +++++++++++++++++++++++++------ arch/mips/cavium-octeon/setup.c | 2 + 2 files changed, 72 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index d113c8ded6e2..a7d9f07b745d 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -560,7 +560,7 @@ static void __init octeon_fdt_rm_ethernet(int node) fdt_nop_node(initial_boot_params, node); } -static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac) +static void __init octeon_fdt_pip_port(int iface, int i, int p, int max) { char name_buffer[20]; int eth; @@ -583,10 +583,9 @@ static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pm phy_addr = cvmx_helper_board_get_mii_address(ipd_port); octeon_fdt_set_phy(eth, phy_addr); - octeon_fdt_set_mac_addr(eth, pmac); } -static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) +static void __init octeon_fdt_pip_iface(int pip, int idx) { char name_buffer[20]; int iface; @@ -602,7 +601,73 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) count = cvmx_helper_ports_on_interface(idx); for (p = 0; p < 16; p++) - octeon_fdt_pip_port(iface, idx, p, count - 1, pmac); + octeon_fdt_pip_port(iface, idx, p, count - 1); +} + +void __init octeon_fill_mac_addresses(void) +{ + const char *alias_prop; + char name_buffer[20]; + u64 mac_addr_base; + int aliases; + int pip; + int i; + + aliases = fdt_path_offset(initial_boot_params, "/aliases"); + if (aliases < 0) + return; + + mac_addr_base = + ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 | + ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 | + ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 | + ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 | + ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 | + (octeon_bootinfo->mac_addr_base[5] & 0xffull); + + for (i = 0; i < 2; i++) { + int mgmt; + + snprintf(name_buffer, sizeof(name_buffer), "mix%d", i); + alias_prop = fdt_getprop(initial_boot_params, aliases, + name_buffer, NULL); + if (!alias_prop) + continue; + mgmt = fdt_path_offset(initial_boot_params, alias_prop); + if (mgmt < 0) + continue; + octeon_fdt_set_mac_addr(mgmt, &mac_addr_base); + } + + alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL); + if (!alias_prop) + return; + + pip = fdt_path_offset(initial_boot_params, alias_prop); + if (pip < 0) + return; + + for (i = 0; i <= 4; i++) { + int iface; + int p; + + snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i); + iface = fdt_subnode_offset(initial_boot_params, pip, + name_buffer); + if (iface < 0) + continue; + for (p = 0; p < 16; p++) { + int eth; + + snprintf(name_buffer, sizeof(name_buffer), + "ethernet@%x", p); + eth = fdt_subnode_offset(initial_boot_params, iface, + name_buffer); + if (eth < 0) + continue; + octeon_fdt_set_mac_addr(eth, &mac_addr_base); + } + } } int __init octeon_prune_device_tree(void) @@ -612,7 +677,6 @@ int __init octeon_prune_device_tree(void) const char *alias_prop; char name_buffer[20]; int aliases; - u64 mac_addr_base; if (fdt_check_header(initial_boot_params)) panic("Corrupt Device Tree."); @@ -623,15 +687,6 @@ int __init octeon_prune_device_tree(void) return -EINVAL; } - - mac_addr_base = - ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 | - ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 | - ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 | - ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 | - ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 | - (octeon_bootinfo->mac_addr_base[5] & 0xffull); - if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX)) max_port = 2; else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX)) @@ -660,7 +715,6 @@ int __init octeon_prune_device_tree(void) } else { int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i); octeon_fdt_set_phy(mgmt, phy_addr); - octeon_fdt_set_mac_addr(mgmt, &mac_addr_base); } } } @@ -670,7 +724,7 @@ int __init octeon_prune_device_tree(void) int pip = fdt_path_offset(initial_boot_params, pip_path); if (pip >= 0) for (i = 0; i <= 4; i++) - octeon_fdt_pip_iface(pip, i, &mac_addr_base); + octeon_fdt_pip_iface(pip, i); } /* I2C */ diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 37ac229bebb6..60f66bbcb620 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1108,6 +1108,7 @@ void __init prom_free_prom_memory(void) } } +void __init octeon_fill_mac_addresses(void); int octeon_prune_device_tree(void); extern const char __appended_dtb; @@ -1143,6 +1144,7 @@ void __init device_tree_init(void) if (do_prune) { octeon_prune_device_tree(); + octeon_fill_mac_addresses(); pr_info("Using internal Device Tree.\n"); } unflatten_and_copy_device_tree(); -- cgit v1.2.3-59-g8ed1b From 377de399a1ad191b1c67aca99cfbc65061639f07 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 24 Feb 2016 00:52:06 +0200 Subject: MIPS: Octeon: device_tree_init: don't fill mac if already set Don't fill MAC address if it's already set. This allows DTB to override the bootinfo. Signed-off-by: Aaro Koskinen Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12589/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index a7d9f07b745d..7aeafedff94e 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -525,10 +526,17 @@ static void __init octeon_fdt_set_phy(int eth, int phy_addr) static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac) { + const u8 *old_mac; + int old_len; u8 new_mac[6]; u64 mac = *pmac; int r; + old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address", + &old_len); + if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac)) + return; + new_mac[0] = (mac >> 40) & 0xff; new_mac[1] = (mac >> 32) & 0xff; new_mac[2] = (mac >> 24) & 0xff; -- cgit v1.2.3-59-g8ed1b From 2296cecf719caad9bcda3c8b82830fe3736ffa90 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 24 Feb 2016 00:52:07 +0200 Subject: MIPS: Octeon: device_tree_init: fill mac addresses when using appended dtb Fill MAC addresses from bootinfo when using appended DTB. Signed-off-by: Aaro Koskinen Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12590/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 60f66bbcb620..64f852b063a8 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1118,11 +1118,13 @@ void __init device_tree_init(void) { const void *fdt; bool do_prune; + bool fill_mac; #ifdef CONFIG_MIPS_ELF_APPENDED_DTB if (!fdt_check_header(&__appended_dtb)) { fdt = &__appended_dtb; do_prune = false; + fill_mac = true; pr_info("Using appended Device Tree.\n"); } else #endif @@ -1131,22 +1133,26 @@ void __init device_tree_init(void) if (fdt_check_header(fdt)) panic("Corrupt Device Tree passed to kernel."); do_prune = false; + fill_mac = false; pr_info("Using passed Device Tree.\n"); } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { fdt = &__dtb_octeon_68xx_begin; do_prune = true; + fill_mac = true; } else { fdt = &__dtb_octeon_3xxx_begin; do_prune = true; + fill_mac = true; } initial_boot_params = (void *)fdt; if (do_prune) { octeon_prune_device_tree(); - octeon_fill_mac_addresses(); pr_info("Using internal Device Tree.\n"); } + if (fill_mac) + octeon_fill_mac_addresses(); unflatten_and_copy_device_tree(); init_octeon_system_type(); } -- cgit v1.2.3-59-g8ed1b From 24bc827beb2b0dea026015914924aede9c278a90 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:46 +0100 Subject: MIPS: lantiq: Make reset_control_ops const The reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Acked-by: John Crispin Cc: linux-mips@linux-mips.org Cc: kernel@pengutronix.de Patchwork: https://patchwork.linux-mips.org/patch/12619/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index bc29bb349e94..1f3460877ed5 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -258,7 +258,7 @@ static int ltq_reset_device(struct reset_controller_dev *rcdev, return ltq_deassert_device(rcdev, id); } -static struct reset_control_ops reset_ops = { +static const struct reset_control_ops reset_ops = { .reset = ltq_reset_device, .assert = ltq_assert_device, .deassert = ltq_deassert_device, -- cgit v1.2.3-59-g8ed1b From b11d022767f78357f08bc3d548e99af1c6cf7808 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:47 +0100 Subject: MIPS: ralink: Make reset_control_ops const The reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Acked-by: John Crispin Cc: linux-mips@linux-mips.org Cc: kernel@pengutronix.de Patchwork: https://patchwork.linux-mips.org/patch/12618/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index ee117c4bc4a3..09ccdd1b8f4d 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -61,7 +61,7 @@ static int ralink_reset_device(struct reset_controller_dev *rcdev, return ralink_deassert_device(rcdev, id); } -static struct reset_control_ops reset_ops = { +static const struct reset_control_ops reset_ops = { .reset = ralink_reset_device, .assert = ralink_assert_device, .deassert = ralink_deassert_device, -- cgit v1.2.3-59-g8ed1b From 2ab71a02c56f8244ac611b5c6e6603c6fe83b966 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 25 Jan 2016 09:50:29 +0100 Subject: MIPS: BCM47xx: Move SPROM driver to drivers/firmware/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadcom ARM home routers store SPROM content in NVRAM just like MIPS ones. To share SPROM code we need to move it out of arch/mips/ to some common place. We already have bcm47xx_nvram in firmware path and SPROM should fit there as well. This driver is responsible for parsing SoC configuration data into a struct shared between ssb and bcma buses. This was tested with BCM4706 & BCM5357C0 (BCM47XX) and BCM4708A0 (ARCH_BCM_5301X). Signed-off-by: Rafał Miłecki Cc: Hauke Mehrtens Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12210/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/bcm47xx/Makefile | 2 +- arch/mips/bcm47xx/bcm47xx_private.h | 3 - arch/mips/bcm47xx/setup.c | 2 +- arch/mips/bcm47xx/sprom.c | 724 ----------------------------- drivers/firmware/broadcom/Kconfig | 11 + drivers/firmware/broadcom/Makefile | 1 + drivers/firmware/broadcom/bcm47xx_sprom.c | 737 ++++++++++++++++++++++++++++++ include/linux/bcm47xx_sprom.h | 24 + 9 files changed, 776 insertions(+), 729 deletions(-) delete mode 100644 arch/mips/bcm47xx/sprom.c create mode 100644 drivers/firmware/broadcom/bcm47xx_sprom.c create mode 100644 include/linux/bcm47xx_sprom.h (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2352917a47a1..882e73c3334e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -197,6 +197,7 @@ config BCM47XX select GPIOLIB select LEDS_GPIO_REGISTER select BCM47XX_NVRAM + select BCM47XX_SPROM help Support for BCM47XX based boards diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index 66bea4ecf449..6d8615074075 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile @@ -3,5 +3,5 @@ # under Linux. # -obj-y += irq.o prom.o serial.o setup.o time.o sprom.o +obj-y += irq.o prom.o serial.o setup.o time.o obj-y += board.o buttons.o leds.o workarounds.o diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h index 41796befa9df..0367ac7286fe 100644 --- a/arch/mips/bcm47xx/bcm47xx_private.h +++ b/arch/mips/bcm47xx/bcm47xx_private.h @@ -10,9 +10,6 @@ /* prom.c */ void __init bcm47xx_prom_highmem_init(void); -/* sprom.c */ -void bcm47xx_sprom_register_fallbacks(void); - /* buttons.c */ int __init bcm47xx_buttons_register(void); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index c807e32d6d81..6054d49e608e 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -28,6 +28,7 @@ #include "bcm47xx_private.h" +#include #include #include #include @@ -151,7 +152,6 @@ void __init plat_mem_setup(void) pr_info("Using bcma bus\n"); #ifdef CONFIG_BCM47XX_BCMA bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; - bcm47xx_sprom_register_fallbacks(); bcm47xx_register_bcma(); bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); #ifdef CONFIG_HIGHMEM diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c deleted file mode 100644 index ca7ad131d057..000000000000 --- a/arch/mips/bcm47xx/sprom.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Copyright (C) 2004 Florian Schirmer - * Copyright (C) 2006 Felix Fietkau - * Copyright (C) 2006 Michael Buesch - * Copyright (C) 2010 Waldemar Brodkorb - * Copyright (C) 2010-2012 Hauke Mehrtens - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -static void create_key(const char *prefix, const char *postfix, - const char *name, char *buf, int len) -{ - if (prefix && postfix) - snprintf(buf, len, "%s%s%s", prefix, name, postfix); - else if (prefix) - snprintf(buf, len, "%s%s", prefix, name); - else if (postfix) - snprintf(buf, len, "%s%s", name, postfix); - else - snprintf(buf, len, "%s", name); -} - -static int get_nvram_var(const char *prefix, const char *postfix, - const char *name, char *buf, int len, bool fallback) -{ - char key[40]; - int err; - - create_key(prefix, postfix, name, key, sizeof(key)); - - err = bcm47xx_nvram_getenv(key, buf, len); - if (fallback && err == -ENOENT && prefix) { - create_key(NULL, postfix, name, key, sizeof(key)); - err = bcm47xx_nvram_getenv(key, buf, len); - } - return err; -} - -#define NVRAM_READ_VAL(type) \ -static void nvram_read_ ## type(const char *prefix, \ - const char *postfix, const char *name, \ - type *val, type allset, bool fallback) \ -{ \ - char buf[100]; \ - int err; \ - type var; \ - \ - err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf), \ - fallback); \ - if (err < 0) \ - return; \ - err = kstrto ## type(strim(buf), 0, &var); \ - if (err) { \ - pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \ - prefix, name, postfix, buf, err); \ - return; \ - } \ - if (allset && var == allset) \ - return; \ - *val = var; \ -} - -NVRAM_READ_VAL(u8) -NVRAM_READ_VAL(s8) -NVRAM_READ_VAL(u16) -NVRAM_READ_VAL(u32) - -#undef NVRAM_READ_VAL - -static void nvram_read_u32_2(const char *prefix, const char *name, - u16 *val_lo, u16 *val_hi, bool fallback) -{ - char buf[100]; - int err; - u32 val; - - err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); - if (err < 0) - return; - err = kstrtou32(strim(buf), 0, &val); - if (err) { - pr_warn("can not parse nvram name %s%s with value %s got %i\n", - prefix, name, buf, err); - return; - } - *val_lo = (val & 0x0000FFFFU); - *val_hi = (val & 0xFFFF0000U) >> 16; -} - -static void nvram_read_leddc(const char *prefix, const char *name, - u8 *leddc_on_time, u8 *leddc_off_time, - bool fallback) -{ - char buf[100]; - int err; - u32 val; - - err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); - if (err < 0) - return; - err = kstrtou32(strim(buf), 0, &val); - if (err) { - pr_warn("can not parse nvram name %s%s with value %s got %i\n", - prefix, name, buf, err); - return; - } - - if (val == 0xffff || val == 0xffffffff) - return; - - *leddc_on_time = val & 0xff; - *leddc_off_time = (val >> 16) & 0xff; -} - -static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) -{ - if (strchr(buf, ':')) - sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], - &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], - &macaddr[5]); - else if (strchr(buf, '-')) - sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], - &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], - &macaddr[5]); - else - pr_warn("Can not parse mac address: %s\n", buf); -} - -static void nvram_read_macaddr(const char *prefix, const char *name, - u8 val[6], bool fallback) -{ - char buf[100]; - int err; - - err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); - if (err < 0) - return; - - bcm47xx_nvram_parse_macaddr(buf, val); -} - -static void nvram_read_alpha2(const char *prefix, const char *name, - char val[2], bool fallback) -{ - char buf[10]; - int err; - - err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); - if (err < 0) - return; - if (buf[0] == '0') - return; - if (strlen(buf) > 2) { - pr_warn("alpha2 is too long %s\n", buf); - return; - } - memcpy(val, buf, 2); -} - -/* This is one-function-only macro, it uses local "sprom" variable! */ -#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \ - if (_revmask & BIT(sprom->revision)) \ - nvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \ - _allset, _fallback) -/* - * Special version of filling function that can be safely called for any SPROM - * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions - * for which the mapping is valid. - * It obviously requires some hexadecimal/bitmasks knowledge, but allows - * writing cleaner code (easy revisions handling). - * Note that while SPROM revision 0 was never used, we still keep BIT(0) - * reserved for it, just to keep numbering sane. - */ -static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - const char *pre = prefix; - bool fb = fallback; - - /* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */ - ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback); - - ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true); - ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb); - ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb); - ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb); - ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb); - ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true); - ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb); - ENTRY(0x00000002, u8, pre, "cc", country_code, 0, fb); - ENTRY(0xfffffff8, u8, pre, "regrev", regrev, 0, fb); - - ENTRY(0xfffffffe, u8, pre, "ledbh0", gpio0, 0xff, fb); - ENTRY(0xfffffffe, u8, pre, "ledbh1", gpio1, 0xff, fb); - ENTRY(0xfffffffe, u8, pre, "ledbh2", gpio2, 0xff, fb); - ENTRY(0xfffffffe, u8, pre, "ledbh3", gpio3, 0xff, fb); - - ENTRY(0x0000070e, u16, pre, "pa0b0", pa0b0, 0, fb); - ENTRY(0x0000070e, u16, pre, "pa0b1", pa0b1, 0, fb); - ENTRY(0x0000070e, u16, pre, "pa0b2", pa0b2, 0, fb); - ENTRY(0x0000070e, u8, pre, "pa0itssit", itssi_bg, 0, fb); - ENTRY(0x0000070e, u8, pre, "pa0maxpwr", maxpwr_bg, 0, fb); - - ENTRY(0x0000070c, u8, pre, "opo", opo, 0, fb); - ENTRY(0xfffffffe, u8, pre, "aa2g", ant_available_bg, 0, fb); - ENTRY(0xfffffffe, u8, pre, "aa5g", ant_available_a, 0, fb); - ENTRY(0x000007fe, s8, pre, "ag0", antenna_gain.a0, 0, fb); - ENTRY(0x000007fe, s8, pre, "ag1", antenna_gain.a1, 0, fb); - ENTRY(0x000007f0, s8, pre, "ag2", antenna_gain.a2, 0, fb); - ENTRY(0x000007f0, s8, pre, "ag3", antenna_gain.a3, 0, fb); - - ENTRY(0x0000070e, u16, pre, "pa1b0", pa1b0, 0, fb); - ENTRY(0x0000070e, u16, pre, "pa1b1", pa1b1, 0, fb); - ENTRY(0x0000070e, u16, pre, "pa1b2", pa1b2, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1lob0", pa1lob0, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1lob1", pa1lob1, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1lob2", pa1lob2, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1hib0", pa1hib0, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1hib1", pa1hib1, 0, fb); - ENTRY(0x0000070c, u16, pre, "pa1hib2", pa1hib2, 0, fb); - ENTRY(0x0000070e, u8, pre, "pa1itssit", itssi_a, 0, fb); - ENTRY(0x0000070e, u8, pre, "pa1maxpwr", maxpwr_a, 0, fb); - ENTRY(0x0000070c, u8, pre, "pa1lomaxpwr", maxpwr_al, 0, fb); - ENTRY(0x0000070c, u8, pre, "pa1himaxpwr", maxpwr_ah, 0, fb); - - ENTRY(0x00000708, u8, pre, "bxa2g", bxa2g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssisav2g", rssisav2g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssismc2g", rssismc2g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssismf2g", rssismf2g, 0, fb); - ENTRY(0x00000708, u8, pre, "bxa5g", bxa5g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssisav5g", rssisav5g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssismc5g", rssismc5g, 0, fb); - ENTRY(0x00000708, u8, pre, "rssismf5g", rssismf5g, 0, fb); - ENTRY(0x00000708, u8, pre, "tri2g", tri2g, 0, fb); - ENTRY(0x00000708, u8, pre, "tri5g", tri5g, 0, fb); - ENTRY(0x00000708, u8, pre, "tri5gl", tri5gl, 0, fb); - ENTRY(0x00000708, u8, pre, "tri5gh", tri5gh, 0, fb); - ENTRY(0x00000708, s8, pre, "rxpo2g", rxpo2g, 0, fb); - ENTRY(0x00000708, s8, pre, "rxpo5g", rxpo5g, 0, fb); - ENTRY(0xfffffff0, u8, pre, "txchain", txchain, 0xf, fb); - ENTRY(0xfffffff0, u8, pre, "rxchain", rxchain, 0xf, fb); - ENTRY(0xfffffff0, u8, pre, "antswitch", antswitch, 0xff, fb); - ENTRY(0x00000700, u8, pre, "tssipos2g", fem.ghz2.tssipos, 0, fb); - ENTRY(0x00000700, u8, pre, "extpagain2g", fem.ghz2.extpa_gain, 0, fb); - ENTRY(0x00000700, u8, pre, "pdetrange2g", fem.ghz2.pdet_range, 0, fb); - ENTRY(0x00000700, u8, pre, "triso2g", fem.ghz2.tr_iso, 0, fb); - ENTRY(0x00000700, u8, pre, "antswctl2g", fem.ghz2.antswlut, 0, fb); - ENTRY(0x00000700, u8, pre, "tssipos5g", fem.ghz5.tssipos, 0, fb); - ENTRY(0x00000700, u8, pre, "extpagain5g", fem.ghz5.extpa_gain, 0, fb); - ENTRY(0x00000700, u8, pre, "pdetrange5g", fem.ghz5.pdet_range, 0, fb); - ENTRY(0x00000700, u8, pre, "triso5g", fem.ghz5.tr_iso, 0, fb); - ENTRY(0x00000700, u8, pre, "antswctl5g", fem.ghz5.antswlut, 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid2ga0", txpid2g[0], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid2ga1", txpid2g[1], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid2ga2", txpid2g[2], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid2ga3", txpid2g[3], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5ga0", txpid5g[0], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5ga1", txpid5g[1], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5ga2", txpid5g[2], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5ga3", txpid5g[3], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gla0", txpid5gl[0], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gla1", txpid5gl[1], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gla2", txpid5gl[2], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gla3", txpid5gl[3], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gha0", txpid5gh[0], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gha1", txpid5gh[1], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gha2", txpid5gh[2], 0, fb); - ENTRY(0x000000f0, u8, pre, "txpid5gha3", txpid5gh[3], 0, fb); - - ENTRY(0xffffff00, u8, pre, "tempthresh", tempthresh, 0, fb); - ENTRY(0xffffff00, u8, pre, "tempoffset", tempoffset, 0, fb); - ENTRY(0xffffff00, u16, pre, "rawtempsense", rawtempsense, 0, fb); - ENTRY(0xffffff00, u8, pre, "measpower", measpower, 0, fb); - ENTRY(0xffffff00, u8, pre, "tempsense_slope", tempsense_slope, 0, fb); - ENTRY(0xffffff00, u8, pre, "tempcorrx", tempcorrx, 0, fb); - ENTRY(0xffffff00, u8, pre, "tempsense_option", tempsense_option, 0, fb); - ENTRY(0x00000700, u8, pre, "freqoffset_corr", freqoffset_corr, 0, fb); - ENTRY(0x00000700, u8, pre, "iqcal_swp_dis", iqcal_swp_dis, 0, fb); - ENTRY(0x00000700, u8, pre, "hw_iqcal_en", hw_iqcal_en, 0, fb); - ENTRY(0x00000700, u8, pre, "elna2g", elna2g, 0, fb); - ENTRY(0x00000700, u8, pre, "elna5g", elna5g, 0, fb); - ENTRY(0xffffff00, u8, pre, "phycal_tempdelta", phycal_tempdelta, 0, fb); - ENTRY(0xffffff00, u8, pre, "temps_period", temps_period, 0, fb); - ENTRY(0xffffff00, u8, pre, "temps_hysteresis", temps_hysteresis, 0, fb); - ENTRY(0xffffff00, u8, pre, "measpower1", measpower1, 0, fb); - ENTRY(0xffffff00, u8, pre, "measpower2", measpower2, 0, fb); - - ENTRY(0x000001f0, u16, pre, "cck2gpo", cck2gpo, 0, fb); - ENTRY(0x000001f0, u32, pre, "ofdm2gpo", ofdm2gpo, 0, fb); - ENTRY(0x000001f0, u32, pre, "ofdm5gpo", ofdm5gpo, 0, fb); - ENTRY(0x000001f0, u32, pre, "ofdm5glpo", ofdm5glpo, 0, fb); - ENTRY(0x000001f0, u32, pre, "ofdm5ghpo", ofdm5ghpo, 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo0", mcs2gpo[0], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo1", mcs2gpo[1], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo2", mcs2gpo[2], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo3", mcs2gpo[3], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo4", mcs2gpo[4], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo5", mcs2gpo[5], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo6", mcs2gpo[6], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs2gpo7", mcs2gpo[7], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo0", mcs5gpo[0], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo1", mcs5gpo[1], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo2", mcs5gpo[2], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo3", mcs5gpo[3], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo4", mcs5gpo[4], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo5", mcs5gpo[5], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo6", mcs5gpo[6], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5gpo7", mcs5gpo[7], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo0", mcs5glpo[0], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo1", mcs5glpo[1], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo2", mcs5glpo[2], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo3", mcs5glpo[3], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo4", mcs5glpo[4], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo5", mcs5glpo[5], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo6", mcs5glpo[6], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5glpo7", mcs5glpo[7], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo0", mcs5ghpo[0], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo1", mcs5ghpo[1], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo2", mcs5ghpo[2], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo3", mcs5ghpo[3], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo4", mcs5ghpo[4], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo5", mcs5ghpo[5], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo6", mcs5ghpo[6], 0, fb); - ENTRY(0x000001f0, u16, pre, "mcs5ghpo7", mcs5ghpo[7], 0, fb); - ENTRY(0x000001f0, u16, pre, "cddpo", cddpo, 0, fb); - ENTRY(0x000001f0, u16, pre, "stbcpo", stbcpo, 0, fb); - ENTRY(0x000001f0, u16, pre, "bw40po", bw40po, 0, fb); - ENTRY(0x000001f0, u16, pre, "bwduppo", bwduppo, 0, fb); - - ENTRY(0xfffffe00, u16, pre, "cckbw202gpo", cckbw202gpo, 0, fb); - ENTRY(0xfffffe00, u16, pre, "cckbw20ul2gpo", cckbw20ul2gpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw202gpo", legofdmbw202gpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw20ul2gpo", legofdmbw20ul2gpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw205glpo", legofdmbw205glpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw20ul5glpo", legofdmbw20ul5glpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw205gmpo", legofdmbw205gmpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw20ul5gmpo", legofdmbw20ul5gmpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw205ghpo", legofdmbw205ghpo, 0, fb); - ENTRY(0x00000600, u32, pre, "legofdmbw20ul5ghpo", legofdmbw20ul5ghpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw202gpo", mcsbw202gpo, 0, fb); - ENTRY(0x00000600, u32, pre, "mcsbw20ul2gpo", mcsbw20ul2gpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw402gpo", mcsbw402gpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw205glpo", mcsbw205glpo, 0, fb); - ENTRY(0x00000600, u32, pre, "mcsbw20ul5glpo", mcsbw20ul5glpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw405glpo", mcsbw405glpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw205gmpo", mcsbw205gmpo, 0, fb); - ENTRY(0x00000600, u32, pre, "mcsbw20ul5gmpo", mcsbw20ul5gmpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw405gmpo", mcsbw405gmpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw205ghpo", mcsbw205ghpo, 0, fb); - ENTRY(0x00000600, u32, pre, "mcsbw20ul5ghpo", mcsbw20ul5ghpo, 0, fb); - ENTRY(0xfffffe00, u32, pre, "mcsbw405ghpo", mcsbw405ghpo, 0, fb); - ENTRY(0x00000600, u16, pre, "mcs32po", mcs32po, 0, fb); - ENTRY(0x00000600, u16, pre, "legofdm40duppo", legofdm40duppo, 0, fb); - ENTRY(0x00000700, u8, pre, "pcieingress_war", pcieingress_war, 0, fb); - - /* TODO: rev 11 support */ - ENTRY(0x00000700, u8, pre, "rxgainerr2ga0", rxgainerr2ga[0], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr2ga1", rxgainerr2ga[1], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr2ga2", rxgainerr2ga[2], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gla0", rxgainerr5gla[0], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gla1", rxgainerr5gla[1], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gla2", rxgainerr5gla[2], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gma0", rxgainerr5gma[0], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gma1", rxgainerr5gma[1], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gma2", rxgainerr5gma[2], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gha0", rxgainerr5gha[0], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gha1", rxgainerr5gha[1], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gha2", rxgainerr5gha[2], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gua0", rxgainerr5gua[0], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gua1", rxgainerr5gua[1], 0, fb); - ENTRY(0x00000700, u8, pre, "rxgainerr5gua2", rxgainerr5gua[2], 0, fb); - - ENTRY(0xfffffe00, u8, pre, "sar2g", sar2g, 0, fb); - ENTRY(0xfffffe00, u8, pre, "sar5g", sar5g, 0, fb); - - /* TODO: rev 11 support */ - ENTRY(0x00000700, u8, pre, "noiselvl2ga0", noiselvl2ga[0], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl2ga1", noiselvl2ga[1], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl2ga2", noiselvl2ga[2], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gla0", noiselvl5gla[0], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gla1", noiselvl5gla[1], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gla2", noiselvl5gla[2], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gma0", noiselvl5gma[0], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gma1", noiselvl5gma[1], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gma2", noiselvl5gma[2], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gha0", noiselvl5gha[0], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gha1", noiselvl5gha[1], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gha2", noiselvl5gha[2], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gua0", noiselvl5gua[0], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gua1", noiselvl5gua[1], 0, fb); - ENTRY(0x00000700, u8, pre, "noiselvl5gua2", noiselvl5gua[2], 0, fb); -} -#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */ - -static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - char postfix[2]; - int i; - - for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { - struct ssb_sprom_core_pwr_info *pwr_info; - - pwr_info = &sprom->core_pwr_info[i]; - - snprintf(postfix, sizeof(postfix), "%i", i); - nvram_read_u8(prefix, postfix, "maxp2ga", - &pwr_info->maxpwr_2g, 0, fallback); - nvram_read_u8(prefix, postfix, "itt2ga", - &pwr_info->itssi_2g, 0, fallback); - nvram_read_u8(prefix, postfix, "itt5ga", - &pwr_info->itssi_5g, 0, fallback); - nvram_read_u16(prefix, postfix, "pa2gw0a", - &pwr_info->pa_2g[0], 0, fallback); - nvram_read_u16(prefix, postfix, "pa2gw1a", - &pwr_info->pa_2g[1], 0, fallback); - nvram_read_u16(prefix, postfix, "pa2gw2a", - &pwr_info->pa_2g[2], 0, fallback); - nvram_read_u8(prefix, postfix, "maxp5ga", - &pwr_info->maxpwr_5g, 0, fallback); - nvram_read_u8(prefix, postfix, "maxp5gha", - &pwr_info->maxpwr_5gh, 0, fallback); - nvram_read_u8(prefix, postfix, "maxp5gla", - &pwr_info->maxpwr_5gl, 0, fallback); - nvram_read_u16(prefix, postfix, "pa5gw0a", - &pwr_info->pa_5g[0], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5gw1a", - &pwr_info->pa_5g[1], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5gw2a", - &pwr_info->pa_5g[2], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5glw0a", - &pwr_info->pa_5gl[0], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5glw1a", - &pwr_info->pa_5gl[1], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5glw2a", - &pwr_info->pa_5gl[2], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5ghw0a", - &pwr_info->pa_5gh[0], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5ghw1a", - &pwr_info->pa_5gh[1], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5ghw2a", - &pwr_info->pa_5gh[2], 0, fallback); - } -} - -static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - char postfix[2]; - int i; - - for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { - struct ssb_sprom_core_pwr_info *pwr_info; - - pwr_info = &sprom->core_pwr_info[i]; - - snprintf(postfix, sizeof(postfix), "%i", i); - nvram_read_u16(prefix, postfix, "pa2gw3a", - &pwr_info->pa_2g[3], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5gw3a", - &pwr_info->pa_5g[3], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5glw3a", - &pwr_info->pa_5gl[3], 0, fallback); - nvram_read_u16(prefix, postfix, "pa5ghw3a", - &pwr_info->pa_5gh[3], 0, fallback); - } -} - -static bool bcm47xx_is_valid_mac(u8 *mac) -{ - return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c); -} - -static int bcm47xx_increase_mac_addr(u8 *mac, u8 num) -{ - u8 *oui = mac + ETH_ALEN/2 - 1; - u8 *p = mac + ETH_ALEN - 1; - - do { - (*p) += num; - if (*p > num) - break; - p--; - num = 1; - } while (p != oui); - - if (p == oui) { - pr_err("unable to fetch mac address\n"); - return -ENOENT; - } - return 0; -} - -static int mac_addr_used = 2; - -static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - bool fb = fallback; - - nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback); - nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0, - fallback); - nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0, - fallback); - - nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback); - nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0, - fallback); - nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0, - fallback); - - nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb); - nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb); - nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb); - - nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); - nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); - - /* The address prefix 00:90:4C is used by Broadcom in their initial - * configuration. When a mac address with the prefix 00:90:4C is used - * all devices from the same series are sharing the same mac address. - * To prevent mac address collisions we replace them with a mac address - * based on the base address. - */ - if (!bcm47xx_is_valid_mac(sprom->il0mac)) { - u8 mac[6]; - - nvram_read_macaddr(NULL, "et0macaddr", mac, false); - if (bcm47xx_is_valid_mac(mac)) { - int err = bcm47xx_increase_mac_addr(mac, mac_addr_used); - - if (!err) { - ether_addr_copy(sprom->il0mac, mac); - mac_addr_used++; - } - } - } -} - -static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, - &sprom->boardflags_hi, fallback); - nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, - &sprom->boardflags2_hi, fallback); -} - -void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback); - bcm47xx_fill_board_data(sprom, prefix, fallback); - - nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback); - - /* Entries requiring custom functions */ - nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); - if (sprom->revision >= 3) - nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, - &sprom->leddc_off_time, fallback); - - switch (sprom->revision) { - case 4: - case 5: - bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); - bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback); - break; - case 8: - case 9: - bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); - break; - } - - bcm47xx_sprom_fill_auto(sprom, prefix, fallback); -} - -#if defined(CONFIG_BCM47XX_SSB) -static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) -{ - char prefix[10]; - - switch (bus->bustype) { - case SSB_BUSTYPE_SSB: - bcm47xx_fill_sprom(out, NULL, false); - return 0; - case SSB_BUSTYPE_PCI: - memset(out, 0, sizeof(struct ssb_sprom)); - snprintf(prefix, sizeof(prefix), "pci/%u/%u/", - bus->host_pci->bus->number + 1, - PCI_SLOT(bus->host_pci->devfn)); - bcm47xx_fill_sprom(out, prefix, false); - return 0; - default: - pr_warn("Unable to fill SPROM for given bustype.\n"); - return -EINVAL; - } -} -#endif - -#if defined(CONFIG_BCM47XX_BCMA) -/* - * Having many NVRAM entries for PCI devices led to repeating prefixes like - * pci/1/1/ all the time and wasting flash space. So at some point Broadcom - * decided to introduce prefixes like 0: 1: 2: etc. - * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0: - * instead of pci/2/1/. - */ -static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size) -{ - size_t prefix_len = strlen(prefix); - size_t short_len = prefix_len - 1; - char nvram_var[10]; - char buf[20]; - int i; - - /* Passed prefix has to end with a slash */ - if (prefix_len <= 0 || prefix[prefix_len - 1] != '/') - return; - - for (i = 0; i < 3; i++) { - if (snprintf(nvram_var, sizeof(nvram_var), "devpath%d", i) <= 0) - continue; - if (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0) - continue; - if (!strcmp(buf, prefix) || - (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) { - snprintf(prefix, prefix_size, "%d:", i); - return; - } - } -} - -static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) -{ - struct bcma_boardinfo *binfo = &bus->boardinfo; - struct bcma_device *core; - char buf[10]; - char *prefix; - bool fallback = false; - - switch (bus->hosttype) { - case BCMA_HOSTTYPE_PCI: - memset(out, 0, sizeof(struct ssb_sprom)); - /* On BCM47XX all PCI buses share the same domain */ - if (config_enabled(CONFIG_BCM47XX)) - snprintf(buf, sizeof(buf), "pci/%u/%u/", - bus->host_pci->bus->number + 1, - PCI_SLOT(bus->host_pci->devfn)); - else - snprintf(buf, sizeof(buf), "pci/%u/%u/", - pci_domain_nr(bus->host_pci->bus) + 1, - bus->host_pci->bus->number); - bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf)); - prefix = buf; - break; - case BCMA_HOSTTYPE_SOC: - memset(out, 0, sizeof(struct ssb_sprom)); - core = bcma_find_core(bus, BCMA_CORE_80211); - if (core) { - snprintf(buf, sizeof(buf), "sb/%u/", - core->core_index); - prefix = buf; - fallback = true; - } else { - prefix = NULL; - } - break; - default: - pr_warn("Unable to fill SPROM for given bustype.\n"); - return -EINVAL; - } - - nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true); - if (!binfo->vendor) - binfo->vendor = SSB_BOARDVENDOR_BCM; - nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true); - - bcm47xx_fill_sprom(out, prefix, fallback); - - return 0; -} -#endif - -/* - * On bcm47xx we need to register SPROM fallback handler very early, so we can't - * use anything like platform device / driver for this. - */ -void bcm47xx_sprom_register_fallbacks(void) -{ -#if defined(CONFIG_BCM47XX_SSB) - if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb)) - pr_warn("Failed to register ssb SPROM handler\n"); -#endif - -#if defined(CONFIG_BCM47XX_BCMA) - if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma)) - pr_warn("Failed to register bcma SPROM handler\n"); -#endif -} diff --git a/drivers/firmware/broadcom/Kconfig b/drivers/firmware/broadcom/Kconfig index 6bed119930dd..3c7e5b741e37 100644 --- a/drivers/firmware/broadcom/Kconfig +++ b/drivers/firmware/broadcom/Kconfig @@ -9,3 +9,14 @@ config BCM47XX_NVRAM This driver provides an easy way to get value of requested parameter. It simply reads content of NVRAM and parses it. It doesn't control any hardware part itself. + +config BCM47XX_SPROM + bool "Broadcom SPROM driver" + depends on BCM47XX_NVRAM + help + Broadcom devices store configuration data in SPROM. Accessing it is + specific to the bus host type, e.g. PCI(e) devices have it mapped in + a PCI BAR. + In case of SoC devices SPROM content is stored on a flash used by + bootloader firmware CFE. This driver provides method to ssb and bcma + drivers to read SPROM on SoC. diff --git a/drivers/firmware/broadcom/Makefile b/drivers/firmware/broadcom/Makefile index d0e683583cd6..f93efc479b8b 100644 --- a/drivers/firmware/broadcom/Makefile +++ b/drivers/firmware/broadcom/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o +obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx_sprom.o diff --git a/drivers/firmware/broadcom/bcm47xx_sprom.c b/drivers/firmware/broadcom/bcm47xx_sprom.c new file mode 100644 index 000000000000..b6eb875d4af3 --- /dev/null +++ b/drivers/firmware/broadcom/bcm47xx_sprom.c @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2004 Florian Schirmer + * Copyright (C) 2006 Felix Fietkau + * Copyright (C) 2006 Michael Buesch + * Copyright (C) 2010 Waldemar Brodkorb + * Copyright (C) 2010-2012 Hauke Mehrtens + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static void create_key(const char *prefix, const char *postfix, + const char *name, char *buf, int len) +{ + if (prefix && postfix) + snprintf(buf, len, "%s%s%s", prefix, name, postfix); + else if (prefix) + snprintf(buf, len, "%s%s", prefix, name); + else if (postfix) + snprintf(buf, len, "%s%s", name, postfix); + else + snprintf(buf, len, "%s", name); +} + +static int get_nvram_var(const char *prefix, const char *postfix, + const char *name, char *buf, int len, bool fallback) +{ + char key[40]; + int err; + + create_key(prefix, postfix, name, key, sizeof(key)); + + err = bcm47xx_nvram_getenv(key, buf, len); + if (fallback && err == -ENOENT && prefix) { + create_key(NULL, postfix, name, key, sizeof(key)); + err = bcm47xx_nvram_getenv(key, buf, len); + } + return err; +} + +#define NVRAM_READ_VAL(type) \ +static void nvram_read_ ## type(const char *prefix, \ + const char *postfix, const char *name, \ + type *val, type allset, bool fallback) \ +{ \ + char buf[100]; \ + int err; \ + type var; \ + \ + err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf), \ + fallback); \ + if (err < 0) \ + return; \ + err = kstrto ## type(strim(buf), 0, &var); \ + if (err) { \ + pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \ + prefix, name, postfix, buf, err); \ + return; \ + } \ + if (allset && var == allset) \ + return; \ + *val = var; \ +} + +NVRAM_READ_VAL(u8) +NVRAM_READ_VAL(s8) +NVRAM_READ_VAL(u16) +NVRAM_READ_VAL(u32) + +#undef NVRAM_READ_VAL + +static void nvram_read_u32_2(const char *prefix, const char *name, + u16 *val_lo, u16 *val_hi, bool fallback) +{ + char buf[100]; + int err; + u32 val; + + err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); + if (err < 0) + return; + err = kstrtou32(strim(buf), 0, &val); + if (err) { + pr_warn("can not parse nvram name %s%s with value %s got %i\n", + prefix, name, buf, err); + return; + } + *val_lo = (val & 0x0000FFFFU); + *val_hi = (val & 0xFFFF0000U) >> 16; +} + +static void nvram_read_leddc(const char *prefix, const char *name, + u8 *leddc_on_time, u8 *leddc_off_time, + bool fallback) +{ + char buf[100]; + int err; + u32 val; + + err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); + if (err < 0) + return; + err = kstrtou32(strim(buf), 0, &val); + if (err) { + pr_warn("can not parse nvram name %s%s with value %s got %i\n", + prefix, name, buf, err); + return; + } + + if (val == 0xffff || val == 0xffffffff) + return; + + *leddc_on_time = val & 0xff; + *leddc_off_time = (val >> 16) & 0xff; +} + +static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) +{ + if (strchr(buf, ':')) + sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], + &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], + &macaddr[5]); + else if (strchr(buf, '-')) + sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], + &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], + &macaddr[5]); + else + pr_warn("Can not parse mac address: %s\n", buf); +} + +static void nvram_read_macaddr(const char *prefix, const char *name, + u8 val[6], bool fallback) +{ + char buf[100]; + int err; + + err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); + if (err < 0) + return; + + bcm47xx_nvram_parse_macaddr(buf, val); +} + +static void nvram_read_alpha2(const char *prefix, const char *name, + char val[2], bool fallback) +{ + char buf[10]; + int err; + + err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); + if (err < 0) + return; + if (buf[0] == '0') + return; + if (strlen(buf) > 2) { + pr_warn("alpha2 is too long %s\n", buf); + return; + } + memcpy(val, buf, 2); +} + +/* This is one-function-only macro, it uses local "sprom" variable! */ +#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \ + if (_revmask & BIT(sprom->revision)) \ + nvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \ + _allset, _fallback) +/* + * Special version of filling function that can be safely called for any SPROM + * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions + * for which the mapping is valid. + * It obviously requires some hexadecimal/bitmasks knowledge, but allows + * writing cleaner code (easy revisions handling). + * Note that while SPROM revision 0 was never used, we still keep BIT(0) + * reserved for it, just to keep numbering sane. + */ +static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom, + const char *prefix, bool fallback) +{ + const char *pre = prefix; + bool fb = fallback; + + /* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */ + ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback); + + ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true); + ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb); + ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb); + ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb); + ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb); + ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true); + ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb); + ENTRY(0x00000002, u8, pre, "cc", country_code, 0, fb); + ENTRY(0xfffffff8, u8, pre, "regrev", regrev, 0, fb); + + ENTRY(0xfffffffe, u8, pre, "ledbh0", gpio0, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh1", gpio1, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh2", gpio2, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh3", gpio3, 0xff, fb); + + ENTRY(0x0000070e, u16, pre, "pa0b0", pa0b0, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa0b1", pa0b1, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa0b2", pa0b2, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa0itssit", itssi_bg, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa0maxpwr", maxpwr_bg, 0, fb); + + ENTRY(0x0000070c, u8, pre, "opo", opo, 0, fb); + ENTRY(0xfffffffe, u8, pre, "aa2g", ant_available_bg, 0, fb); + ENTRY(0xfffffffe, u8, pre, "aa5g", ant_available_a, 0, fb); + ENTRY(0x000007fe, s8, pre, "ag0", antenna_gain.a0, 0, fb); + ENTRY(0x000007fe, s8, pre, "ag1", antenna_gain.a1, 0, fb); + ENTRY(0x000007f0, s8, pre, "ag2", antenna_gain.a2, 0, fb); + ENTRY(0x000007f0, s8, pre, "ag3", antenna_gain.a3, 0, fb); + + ENTRY(0x0000070e, u16, pre, "pa1b0", pa1b0, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa1b1", pa1b1, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa1b2", pa1b2, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob0", pa1lob0, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob1", pa1lob1, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob2", pa1lob2, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib0", pa1hib0, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib1", pa1hib1, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib2", pa1hib2, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa1itssit", itssi_a, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa1maxpwr", maxpwr_a, 0, fb); + ENTRY(0x0000070c, u8, pre, "pa1lomaxpwr", maxpwr_al, 0, fb); + ENTRY(0x0000070c, u8, pre, "pa1himaxpwr", maxpwr_ah, 0, fb); + + ENTRY(0x00000708, u8, pre, "bxa2g", bxa2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssisav2g", rssisav2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismc2g", rssismc2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismf2g", rssismf2g, 0, fb); + ENTRY(0x00000708, u8, pre, "bxa5g", bxa5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssisav5g", rssisav5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismc5g", rssismc5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismf5g", rssismf5g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri2g", tri2g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5g", tri5g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5gl", tri5gl, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5gh", tri5gh, 0, fb); + ENTRY(0x00000708, s8, pre, "rxpo2g", rxpo2g, 0, fb); + ENTRY(0x00000708, s8, pre, "rxpo5g", rxpo5g, 0, fb); + ENTRY(0xfffffff0, u8, pre, "txchain", txchain, 0xf, fb); + ENTRY(0xfffffff0, u8, pre, "rxchain", rxchain, 0xf, fb); + ENTRY(0xfffffff0, u8, pre, "antswitch", antswitch, 0xff, fb); + ENTRY(0x00000700, u8, pre, "tssipos2g", fem.ghz2.tssipos, 0, fb); + ENTRY(0x00000700, u8, pre, "extpagain2g", fem.ghz2.extpa_gain, 0, fb); + ENTRY(0x00000700, u8, pre, "pdetrange2g", fem.ghz2.pdet_range, 0, fb); + ENTRY(0x00000700, u8, pre, "triso2g", fem.ghz2.tr_iso, 0, fb); + ENTRY(0x00000700, u8, pre, "antswctl2g", fem.ghz2.antswlut, 0, fb); + ENTRY(0x00000700, u8, pre, "tssipos5g", fem.ghz5.tssipos, 0, fb); + ENTRY(0x00000700, u8, pre, "extpagain5g", fem.ghz5.extpa_gain, 0, fb); + ENTRY(0x00000700, u8, pre, "pdetrange5g", fem.ghz5.pdet_range, 0, fb); + ENTRY(0x00000700, u8, pre, "triso5g", fem.ghz5.tr_iso, 0, fb); + ENTRY(0x00000700, u8, pre, "antswctl5g", fem.ghz5.antswlut, 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga0", txpid2g[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga1", txpid2g[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga2", txpid2g[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga3", txpid2g[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga0", txpid5g[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga1", txpid5g[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga2", txpid5g[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga3", txpid5g[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla0", txpid5gl[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla1", txpid5gl[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla2", txpid5gl[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla3", txpid5gl[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha0", txpid5gh[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha1", txpid5gh[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha2", txpid5gh[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha3", txpid5gh[3], 0, fb); + + ENTRY(0xffffff00, u8, pre, "tempthresh", tempthresh, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempoffset", tempoffset, 0, fb); + ENTRY(0xffffff00, u16, pre, "rawtempsense", rawtempsense, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower", measpower, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempsense_slope", tempsense_slope, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempcorrx", tempcorrx, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempsense_option", tempsense_option, 0, fb); + ENTRY(0x00000700, u8, pre, "freqoffset_corr", freqoffset_corr, 0, fb); + ENTRY(0x00000700, u8, pre, "iqcal_swp_dis", iqcal_swp_dis, 0, fb); + ENTRY(0x00000700, u8, pre, "hw_iqcal_en", hw_iqcal_en, 0, fb); + ENTRY(0x00000700, u8, pre, "elna2g", elna2g, 0, fb); + ENTRY(0x00000700, u8, pre, "elna5g", elna5g, 0, fb); + ENTRY(0xffffff00, u8, pre, "phycal_tempdelta", phycal_tempdelta, 0, fb); + ENTRY(0xffffff00, u8, pre, "temps_period", temps_period, 0, fb); + ENTRY(0xffffff00, u8, pre, "temps_hysteresis", temps_hysteresis, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower1", measpower1, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower2", measpower2, 0, fb); + + ENTRY(0x000001f0, u16, pre, "cck2gpo", cck2gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm2gpo", ofdm2gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5gpo", ofdm5gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5glpo", ofdm5glpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5ghpo", ofdm5ghpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo0", mcs2gpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo1", mcs2gpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo2", mcs2gpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo3", mcs2gpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo4", mcs2gpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo5", mcs2gpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo6", mcs2gpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo7", mcs2gpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo0", mcs5gpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo1", mcs5gpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo2", mcs5gpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo3", mcs5gpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo4", mcs5gpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo5", mcs5gpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo6", mcs5gpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo7", mcs5gpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo0", mcs5glpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo1", mcs5glpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo2", mcs5glpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo3", mcs5glpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo4", mcs5glpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo5", mcs5glpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo6", mcs5glpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo7", mcs5glpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo0", mcs5ghpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo1", mcs5ghpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo2", mcs5ghpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo3", mcs5ghpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo4", mcs5ghpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo5", mcs5ghpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo6", mcs5ghpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo7", mcs5ghpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "cddpo", cddpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "stbcpo", stbcpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "bw40po", bw40po, 0, fb); + ENTRY(0x000001f0, u16, pre, "bwduppo", bwduppo, 0, fb); + + ENTRY(0xfffffe00, u16, pre, "cckbw202gpo", cckbw202gpo, 0, fb); + ENTRY(0xfffffe00, u16, pre, "cckbw20ul2gpo", cckbw20ul2gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw202gpo", legofdmbw202gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul2gpo", legofdmbw20ul2gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205glpo", legofdmbw205glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5glpo", legofdmbw20ul5glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205gmpo", legofdmbw205gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5gmpo", legofdmbw20ul5gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205ghpo", legofdmbw205ghpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5ghpo", legofdmbw20ul5ghpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw202gpo", mcsbw202gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul2gpo", mcsbw20ul2gpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw402gpo", mcsbw402gpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205glpo", mcsbw205glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5glpo", mcsbw20ul5glpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405glpo", mcsbw405glpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205gmpo", mcsbw205gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5gmpo", mcsbw20ul5gmpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405gmpo", mcsbw405gmpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205ghpo", mcsbw205ghpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5ghpo", mcsbw20ul5ghpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405ghpo", mcsbw405ghpo, 0, fb); + ENTRY(0x00000600, u16, pre, "mcs32po", mcs32po, 0, fb); + ENTRY(0x00000600, u16, pre, "legofdm40duppo", legofdm40duppo, 0, fb); + ENTRY(0x00000700, u8, pre, "pcieingress_war", pcieingress_war, 0, fb); + + /* TODO: rev 11 support */ + ENTRY(0x00000700, u8, pre, "rxgainerr2ga0", rxgainerr2ga[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr2ga1", rxgainerr2ga[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr2ga2", rxgainerr2ga[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla0", rxgainerr5gla[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla1", rxgainerr5gla[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla2", rxgainerr5gla[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma0", rxgainerr5gma[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma1", rxgainerr5gma[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma2", rxgainerr5gma[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha0", rxgainerr5gha[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha1", rxgainerr5gha[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha2", rxgainerr5gha[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua0", rxgainerr5gua[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua1", rxgainerr5gua[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua2", rxgainerr5gua[2], 0, fb); + + ENTRY(0xfffffe00, u8, pre, "sar2g", sar2g, 0, fb); + ENTRY(0xfffffe00, u8, pre, "sar5g", sar5g, 0, fb); + + /* TODO: rev 11 support */ + ENTRY(0x00000700, u8, pre, "noiselvl2ga0", noiselvl2ga[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl2ga1", noiselvl2ga[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl2ga2", noiselvl2ga[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla0", noiselvl5gla[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla1", noiselvl5gla[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla2", noiselvl5gla[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma0", noiselvl5gma[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma1", noiselvl5gma[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma2", noiselvl5gma[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha0", noiselvl5gha[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha1", noiselvl5gha[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha2", noiselvl5gha[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua0", noiselvl5gua[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua1", noiselvl5gua[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua2", noiselvl5gua[2], 0, fb); +} +#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */ + +static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, + const char *prefix, bool fallback) +{ + char postfix[2]; + int i; + + for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { + struct ssb_sprom_core_pwr_info *pwr_info; + + pwr_info = &sprom->core_pwr_info[i]; + + snprintf(postfix, sizeof(postfix), "%i", i); + nvram_read_u8(prefix, postfix, "maxp2ga", + &pwr_info->maxpwr_2g, 0, fallback); + nvram_read_u8(prefix, postfix, "itt2ga", + &pwr_info->itssi_2g, 0, fallback); + nvram_read_u8(prefix, postfix, "itt5ga", + &pwr_info->itssi_5g, 0, fallback); + nvram_read_u16(prefix, postfix, "pa2gw0a", + &pwr_info->pa_2g[0], 0, fallback); + nvram_read_u16(prefix, postfix, "pa2gw1a", + &pwr_info->pa_2g[1], 0, fallback); + nvram_read_u16(prefix, postfix, "pa2gw2a", + &pwr_info->pa_2g[2], 0, fallback); + nvram_read_u8(prefix, postfix, "maxp5ga", + &pwr_info->maxpwr_5g, 0, fallback); + nvram_read_u8(prefix, postfix, "maxp5gha", + &pwr_info->maxpwr_5gh, 0, fallback); + nvram_read_u8(prefix, postfix, "maxp5gla", + &pwr_info->maxpwr_5gl, 0, fallback); + nvram_read_u16(prefix, postfix, "pa5gw0a", + &pwr_info->pa_5g[0], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5gw1a", + &pwr_info->pa_5g[1], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5gw2a", + &pwr_info->pa_5g[2], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5glw0a", + &pwr_info->pa_5gl[0], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5glw1a", + &pwr_info->pa_5gl[1], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5glw2a", + &pwr_info->pa_5gl[2], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5ghw0a", + &pwr_info->pa_5gh[0], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5ghw1a", + &pwr_info->pa_5gh[1], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5ghw2a", + &pwr_info->pa_5gh[2], 0, fallback); + } +} + +static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, + const char *prefix, bool fallback) +{ + char postfix[2]; + int i; + + for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { + struct ssb_sprom_core_pwr_info *pwr_info; + + pwr_info = &sprom->core_pwr_info[i]; + + snprintf(postfix, sizeof(postfix), "%i", i); + nvram_read_u16(prefix, postfix, "pa2gw3a", + &pwr_info->pa_2g[3], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5gw3a", + &pwr_info->pa_5g[3], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5glw3a", + &pwr_info->pa_5gl[3], 0, fallback); + nvram_read_u16(prefix, postfix, "pa5ghw3a", + &pwr_info->pa_5gh[3], 0, fallback); + } +} + +static bool bcm47xx_is_valid_mac(u8 *mac) +{ + return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c); +} + +static int bcm47xx_increase_mac_addr(u8 *mac, u8 num) +{ + u8 *oui = mac + ETH_ALEN/2 - 1; + u8 *p = mac + ETH_ALEN - 1; + + do { + (*p) += num; + if (*p > num) + break; + p--; + num = 1; + } while (p != oui); + + if (p == oui) { + pr_err("unable to fetch mac address\n"); + return -ENOENT; + } + return 0; +} + +static int mac_addr_used = 2; + +static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, + const char *prefix, bool fallback) +{ + bool fb = fallback; + + nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback); + nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0, + fallback); + nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0, + fallback); + + nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback); + nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0, + fallback); + nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0, + fallback); + + nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb); + nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb); + nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb); + + nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); + nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); + + /* The address prefix 00:90:4C is used by Broadcom in their initial + * configuration. When a mac address with the prefix 00:90:4C is used + * all devices from the same series are sharing the same mac address. + * To prevent mac address collisions we replace them with a mac address + * based on the base address. + */ + if (!bcm47xx_is_valid_mac(sprom->il0mac)) { + u8 mac[6]; + + nvram_read_macaddr(NULL, "et0macaddr", mac, false); + if (bcm47xx_is_valid_mac(mac)) { + int err = bcm47xx_increase_mac_addr(mac, mac_addr_used); + + if (!err) { + ether_addr_copy(sprom->il0mac, mac); + mac_addr_used++; + } + } + } +} + +static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, + bool fallback) +{ + nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, + &sprom->boardflags_hi, fallback); + nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, + &sprom->boardflags2_hi, fallback); +} + +void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, + bool fallback) +{ + bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback); + bcm47xx_fill_board_data(sprom, prefix, fallback); + + nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback); + + /* Entries requiring custom functions */ + nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); + if (sprom->revision >= 3) + nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, + &sprom->leddc_off_time, fallback); + + switch (sprom->revision) { + case 4: + case 5: + bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); + bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback); + break; + case 8: + case 9: + bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); + break; + } + + bcm47xx_sprom_fill_auto(sprom, prefix, fallback); +} + +#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM) +static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) +{ + char prefix[10]; + + switch (bus->bustype) { + case SSB_BUSTYPE_SSB: + bcm47xx_fill_sprom(out, NULL, false); + return 0; + case SSB_BUSTYPE_PCI: + memset(out, 0, sizeof(struct ssb_sprom)); + snprintf(prefix, sizeof(prefix), "pci/%u/%u/", + bus->host_pci->bus->number + 1, + PCI_SLOT(bus->host_pci->devfn)); + bcm47xx_fill_sprom(out, prefix, false); + return 0; + default: + pr_warn("Unable to fill SPROM for given bustype.\n"); + return -EINVAL; + } +} +#endif + +#if IS_BUILTIN(CONFIG_BCMA) +/* + * Having many NVRAM entries for PCI devices led to repeating prefixes like + * pci/1/1/ all the time and wasting flash space. So at some point Broadcom + * decided to introduce prefixes like 0: 1: 2: etc. + * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0: + * instead of pci/2/1/. + */ +static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size) +{ + size_t prefix_len = strlen(prefix); + size_t short_len = prefix_len - 1; + char nvram_var[10]; + char buf[20]; + int i; + + /* Passed prefix has to end with a slash */ + if (prefix_len <= 0 || prefix[prefix_len - 1] != '/') + return; + + for (i = 0; i < 3; i++) { + if (snprintf(nvram_var, sizeof(nvram_var), "devpath%d", i) <= 0) + continue; + if (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0) + continue; + if (!strcmp(buf, prefix) || + (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) { + snprintf(prefix, prefix_size, "%d:", i); + return; + } + } +} + +static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) +{ + struct bcma_boardinfo *binfo = &bus->boardinfo; + struct bcma_device *core; + char buf[10]; + char *prefix; + bool fallback = false; + + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + memset(out, 0, sizeof(struct ssb_sprom)); + /* On BCM47XX all PCI buses share the same domain */ + if (config_enabled(CONFIG_BCM47XX)) + snprintf(buf, sizeof(buf), "pci/%u/%u/", + bus->host_pci->bus->number + 1, + PCI_SLOT(bus->host_pci->devfn)); + else + snprintf(buf, sizeof(buf), "pci/%u/%u/", + pci_domain_nr(bus->host_pci->bus) + 1, + bus->host_pci->bus->number); + bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf)); + prefix = buf; + break; + case BCMA_HOSTTYPE_SOC: + memset(out, 0, sizeof(struct ssb_sprom)); + core = bcma_find_core(bus, BCMA_CORE_80211); + if (core) { + snprintf(buf, sizeof(buf), "sb/%u/", + core->core_index); + prefix = buf; + fallback = true; + } else { + prefix = NULL; + } + break; + default: + pr_warn("Unable to fill SPROM for given bustype.\n"); + return -EINVAL; + } + + nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true); + if (!binfo->vendor) + binfo->vendor = SSB_BOARDVENDOR_BCM; + nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true); + + bcm47xx_fill_sprom(out, prefix, fallback); + + return 0; +} +#endif + +static unsigned int bcm47xx_sprom_registered; + +/* + * On bcm47xx we need to register SPROM fallback handler very early, so we can't + * use anything like platform device / driver for this. + */ +int bcm47xx_sprom_register_fallbacks(void) +{ + if (bcm47xx_sprom_registered) + return 0; + +#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM) + if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb)) + pr_warn("Failed to register ssb SPROM handler\n"); +#endif + +#if IS_BUILTIN(CONFIG_BCMA) + if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma)) + pr_warn("Failed to register bcma SPROM handler\n"); +#endif + + bcm47xx_sprom_registered = 1; + + return 0; +} + +fs_initcall(bcm47xx_sprom_register_fallbacks); diff --git a/include/linux/bcm47xx_sprom.h b/include/linux/bcm47xx_sprom.h new file mode 100644 index 000000000000..c06b47c84e1a --- /dev/null +++ b/include/linux/bcm47xx_sprom.h @@ -0,0 +1,24 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __BCM47XX_SPROM_H +#define __BCM47XX_SPROM_H + +#include +#include +#include + +#ifdef CONFIG_BCM47XX_SPROM +int bcm47xx_sprom_register_fallbacks(void); +#else +static inline int bcm47xx_sprom_register_fallbacks(void) +{ + return -ENOTSUPP; +}; +#endif + +#endif /* __BCM47XX_SPROM_H */ -- cgit v1.2.3-59-g8ed1b From 99a7a234c890177c4d4f2b0fb02317ef19c364a2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 9 Mar 2016 22:08:42 +0200 Subject: MIPS: panic immediately when panic_on_oops MIPS wants to sleep 5 seconds before panicking when panic_on_oops is set, with no apparent reason. Remove this feature, since some users may want their systems to fail as quickly as possible. Users who want to delay reboot after panic can use PANIC_TIMEOUT. Signed-off-by: Aaro Koskinen Cc: James E.J. Bottomley Cc: Helge Deller Cc: linux-mips@linux-mips.org Cc: linux-parisc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12845/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 3cbd98729ab1..82c2fcf7e585 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -399,11 +399,8 @@ void __noreturn die(const char *str, struct pt_regs *regs) if (in_interrupt()) panic("Fatal exception in interrupt"); - if (panic_on_oops) { - printk(KERN_EMERG "Fatal exception: panic in 5 seconds"); - ssleep(5); + if (panic_on_oops) panic("Fatal exception"); - } if (regs && kexec_should_crash(current)) crash_kexec(regs); -- cgit v1.2.3-59-g8ed1b From fa0a497b9e13cd3c494dbbb93b156752fd15fdd2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 8 Mar 2016 23:32:26 +0200 Subject: MIPS: Octeon: Add DTS for D-Link DSR-1000N Add DTS for D-Link DSR-1000N that is usable as is without any "pruning" with APPENDED_DTB. Split out the common parts from octeon_3xxx.dts into octeon_3xxx.dtsi. Compared to builtin generic DTB, we can specificy fixed links properly and avoid probing non-existent I2C devices. Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12840/ Signed-off-by: Ralf Baechle --- .../boot/dts/cavium-octeon/dlink_dsr-1000n.dts | 78 +++++++ arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts | 205 +----------------- arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi | 231 +++++++++++++++++++++ 3 files changed, 312 insertions(+), 202 deletions(-) create mode 100644 arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts create mode 100644 arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi (limited to 'arch') diff --git a/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts b/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts new file mode 100644 index 000000000000..d6bc994f736f --- /dev/null +++ b/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts @@ -0,0 +1,78 @@ +/* + * Device tree source for D-Link DSR-1000N. + * + * Written by: Aaro Koskinen + * + * 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/ "octeon_3xxx.dtsi" + +/ { + model = "dlink,dsr-1000n"; + + soc@0 { + smi0: mdio@1180000001800 { + phy8: ethernet-phy@8 { + reg = <8>; + compatible = "ethernet-phy-ieee802.3-c22"; + }; + }; + + pip: pip@11800a0000000 { + interface@0 { + ethernet@0 { + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + ethernet@1 { + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + ethernet@2 { + phy-handle = <&phy8>; + }; + }; + }; + + twsi0: i2c@1180000001000 { + rtc@68 { + compatible = "dallas,ds1337"; + reg = <0x68>; + }; + }; + + uart0: serial@1180000000800 { + clock-frequency = <500000000>; + }; + + usbn: usbn@1180068000000 { + refclk-frequency = <12000000>; + refclk-type = "crystal"; + }; + }; + + leds { + compatible = "gpio-leds"; + + usb1 { + label = "usb1"; + gpios = <&gpio 9 1>; /* Active low */ + }; + + usb2 { + label = "usb2"; + gpios = <&gpio 10 1>; /* Active low */ + }; + }; + + aliases { + pip = &pip; + }; +}; diff --git a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts index 9c48e0586ba7..de61f02d3ef6 100644 --- a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts +++ b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts @@ -1,4 +1,3 @@ -/dts-v1/; /* * OCTEON 3XXX, 5XXX, 63XX device tree skeleton. * @@ -6,56 +5,12 @@ * use. Because of this, it contains a super-set of the available * devices and properties. */ -/ { - compatible = "cavium,octeon-3860"; - #address-cells = <2>; - #size-cells = <2>; - interrupt-parent = <&ciu>; - - soc@0 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; /* Direct mapping */ - - ciu: interrupt-controller@1070000000000 { - compatible = "cavium,octeon-3860-ciu"; - interrupt-controller; - /* Interrupts are specified by two parts: - * 1) Controller register (0 or 1) - * 2) Bit within the register (0..63) - */ - #interrupt-cells = <2>; - reg = <0x10700 0x00000000 0x0 0x7000>; - }; - gpio: gpio-controller@1070000000800 { - #gpio-cells = <2>; - compatible = "cavium,octeon-3860-gpio"; - reg = <0x10700 0x00000800 0x0 0x100>; - gpio-controller; - /* Interrupts are specified by two parts: - * 1) GPIO pin number (0..15) - * 2) Triggering (1 - edge rising - * 2 - edge falling - * 4 - level active high - * 8 - level active low) - */ - interrupt-controller; - #interrupt-cells = <2>; - /* The GPIO pin connect to 16 consecutive CUI bits */ - interrupts = <0 16>, <0 17>, <0 18>, <0 19>, - <0 20>, <0 21>, <0 22>, <0 23>, - <0 24>, <0 25>, <0 26>, <0 27>, - <0 28>, <0 29>, <0 30>, <0 31>; - }; +/include/ "octeon_3xxx.dtsi" +/ { + soc@0 { smi0: mdio@1180000001800 { - compatible = "cavium,octeon-3860-mdio"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x11800 0x00001800 0x0 0x40>; - phy0: ethernet-phy@0 { compatible = "marvell,88e1118"; marvell,reg-init = @@ -220,35 +175,16 @@ }; pip: pip@11800a0000000 { - compatible = "cavium,octeon-3860-pip"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x11800 0xa0000000 0x0 0x2000>; - interface@0 { - compatible = "cavium,octeon-3860-pip-interface"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; /* interface */ - ethernet@0 { - compatible = "cavium,octeon-3860-pip-port"; - reg = <0x0>; /* Port */ - local-mac-address = [ 00 00 00 00 00 00 ]; phy-handle = <&phy2>; cavium,alt-phy-handle = <&phy100>; }; ethernet@1 { - compatible = "cavium,octeon-3860-pip-port"; - reg = <0x1>; /* Port */ - local-mac-address = [ 00 00 00 00 00 00 ]; phy-handle = <&phy3>; cavium,alt-phy-handle = <&phy101>; }; ethernet@2 { - compatible = "cavium,octeon-3860-pip-port"; - reg = <0x2>; /* Port */ - local-mac-address = [ 00 00 00 00 00 00 ]; phy-handle = <&phy4>; cavium,alt-phy-handle = <&phy102>; }; @@ -322,11 +258,6 @@ }; interface@1 { - compatible = "cavium,octeon-3860-pip-interface"; - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; /* interface */ - ethernet@0 { compatible = "cavium,octeon-3860-pip-port"; reg = <0x0>; /* Port */ @@ -355,13 +286,6 @@ }; twsi0: i2c@1180000001000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "cavium,octeon-3860-twsi"; - reg = <0x11800 0x00001000 0x0 0x200>; - interrupts = <0 45>; - clock-frequency = <100000>; - rtc@68 { compatible = "dallas,ds1337"; reg = <0x68>; @@ -381,15 +305,6 @@ clock-frequency = <100000>; }; - uart0: serial@1180000000800 { - compatible = "cavium,octeon-3860-uart","ns16550"; - reg = <0x11800 0x00000800 0x0 0x400>; - clock-frequency = <0>; - current-speed = <115200>; - reg-shift = <3>; - interrupts = <0 34>; - }; - uart1: serial@1180000000c00 { compatible = "cavium,octeon-3860-uart","ns16550"; reg = <0x11800 0x00000c00 0x0 0x400>; @@ -409,98 +324,6 @@ }; bootbus: bootbus@1180000000000 { - compatible = "cavium,octeon-3860-bootbus"; - reg = <0x11800 0x00000000 0x0 0x200>; - /* The chip select number and offset */ - #address-cells = <2>; - /* The size of the chip select region */ - #size-cells = <1>; - ranges = <0 0 0x0 0x1f400000 0xc00000>, - <1 0 0x10000 0x30000000 0>, - <2 0 0x10000 0x40000000 0>, - <3 0 0x10000 0x50000000 0>, - <4 0 0x0 0x1d020000 0x10000>, - <5 0 0x0 0x1d040000 0x10000>, - <6 0 0x0 0x1d050000 0x10000>, - <7 0 0x10000 0x90000000 0>; - - cavium,cs-config@0 { - compatible = "cavium,octeon-3860-bootbus-config"; - cavium,cs-index = <0>; - cavium,t-adr = <20>; - cavium,t-ce = <60>; - cavium,t-oe = <60>; - cavium,t-we = <45>; - cavium,t-rd-hld = <35>; - cavium,t-wr-hld = <45>; - cavium,t-pause = <0>; - cavium,t-wait = <0>; - cavium,t-page = <35>; - cavium,t-rd-dly = <0>; - - cavium,pages = <0>; - cavium,bus-width = <8>; - }; - cavium,cs-config@4 { - compatible = "cavium,octeon-3860-bootbus-config"; - cavium,cs-index = <4>; - cavium,t-adr = <320>; - cavium,t-ce = <320>; - cavium,t-oe = <320>; - cavium,t-we = <320>; - cavium,t-rd-hld = <320>; - cavium,t-wr-hld = <320>; - cavium,t-pause = <320>; - cavium,t-wait = <320>; - cavium,t-page = <320>; - cavium,t-rd-dly = <0>; - - cavium,pages = <0>; - cavium,bus-width = <8>; - }; - cavium,cs-config@5 { - compatible = "cavium,octeon-3860-bootbus-config"; - cavium,cs-index = <5>; - cavium,t-adr = <5>; - cavium,t-ce = <300>; - cavium,t-oe = <125>; - cavium,t-we = <150>; - cavium,t-rd-hld = <100>; - cavium,t-wr-hld = <30>; - cavium,t-pause = <0>; - cavium,t-wait = <30>; - cavium,t-page = <320>; - cavium,t-rd-dly = <0>; - - cavium,pages = <0>; - cavium,bus-width = <16>; - }; - cavium,cs-config@6 { - compatible = "cavium,octeon-3860-bootbus-config"; - cavium,cs-index = <6>; - cavium,t-adr = <5>; - cavium,t-ce = <300>; - cavium,t-oe = <270>; - cavium,t-we = <150>; - cavium,t-rd-hld = <100>; - cavium,t-wr-hld = <70>; - cavium,t-pause = <0>; - cavium,t-wait = <0>; - cavium,t-page = <320>; - cavium,t-rd-dly = <0>; - - cavium,pages = <0>; - cavium,wait-mode; - cavium,bus-width = <16>; - }; - - flash0: nor@0,0 { - compatible = "cfi-flash"; - reg = <0 0 0x800000>; - #address-cells = <1>; - #size-cells = <1>; - }; - led0: led-display@4,0 { compatible = "avago,hdsp-253x"; reg = <4 0x20 0x20>, <4 0 0x20>; @@ -515,17 +338,6 @@ }; }; - dma0: dma-engine@1180000000100 { - compatible = "cavium,octeon-5750-bootbus-dma"; - reg = <0x11800 0x00000100 0x0 0x8>; - interrupts = <0 63>; - }; - dma1: dma-engine@1180000000108 { - compatible = "cavium,octeon-5750-bootbus-dma"; - reg = <0x11800 0x00000108 0x0 0x8>; - interrupts = <0 63>; - }; - uctl: uctl@118006f000000 { compatible = "cavium,octeon-6335-uctl"; reg = <0x11800 0x6f000000 0x0 0x100>; @@ -552,21 +364,10 @@ }; usbn: usbn@1180068000000 { - compatible = "cavium,octeon-5750-usbn"; - reg = <0x11800 0x68000000 0x0 0x1000>; - ranges; /* Direct mapping */ - #address-cells = <2>; - #size-cells = <2>; /* 12MHz, 24MHz and 48MHz allowed */ refclk-frequency = <12000000>; /* Either "crystal" or "external" */ refclk-type = "crystal"; - - usbc@16f0010000000 { - compatible = "cavium,octeon-5750-usbc"; - reg = <0x16f00 0x10000000 0x0 0x80000>; - interrupts = <0 56>; - }; }; }; diff --git a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi new file mode 100644 index 000000000000..5302148e05a3 --- /dev/null +++ b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi @@ -0,0 +1,231 @@ +/* OCTEON 3XXX DTS common parts. */ + +/dts-v1/; + +/ { + compatible = "cavium,octeon-3860"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&ciu>; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; /* Direct mapping */ + + ciu: interrupt-controller@1070000000000 { + compatible = "cavium,octeon-3860-ciu"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Controller register (0 or 1) + * 2) Bit within the register (0..63) + */ + #interrupt-cells = <2>; + reg = <0x10700 0x00000000 0x0 0x7000>; + }; + + gpio: gpio-controller@1070000000800 { + #gpio-cells = <2>; + compatible = "cavium,octeon-3860-gpio"; + reg = <0x10700 0x00000800 0x0 0x100>; + gpio-controller; + /* Interrupts are specified by two parts: + * 1) GPIO pin number (0..15) + * 2) Triggering (1 - edge rising + * 2 - edge falling + * 4 - level active high + * 8 - level active low) + */ + interrupt-controller; + #interrupt-cells = <2>; + /* The GPIO pin connect to 16 consecutive CUI bits */ + interrupts = <0 16>, <0 17>, <0 18>, <0 19>, + <0 20>, <0 21>, <0 22>, <0 23>, + <0 24>, <0 25>, <0 26>, <0 27>, + <0 28>, <0 29>, <0 30>, <0 31>; + }; + + smi0: mdio@1180000001800 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00001800 0x0 0x40>; + }; + + pip: pip@11800a0000000 { + compatible = "cavium,octeon-3860-pip"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0xa0000000 0x0 0x2000>; + + interface@0 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + + interface@1 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; /* interface */ + }; + }; + + twsi0: i2c@1180000001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001000 0x0 0x200>; + interrupts = <0 45>; + clock-frequency = <100000>; + }; + + uart0: serial@1180000000800 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000800 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <0 34>; + }; + + bootbus: bootbus@1180000000000 { + compatible = "cavium,octeon-3860-bootbus"; + reg = <0x11800 0x00000000 0x0 0x200>; + /* The chip select number and offset */ + #address-cells = <2>; + /* The size of the chip select region */ + #size-cells = <1>; + ranges = <0 0 0x0 0x1f400000 0xc00000>, + <1 0 0x10000 0x30000000 0>, + <2 0 0x10000 0x40000000 0>, + <3 0 0x10000 0x50000000 0>, + <4 0 0x0 0x1d020000 0x10000>, + <5 0 0x0 0x1d040000 0x10000>, + <6 0 0x0 0x1d050000 0x10000>, + <7 0 0x10000 0x90000000 0>; + + cavium,cs-config@0 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <0>; + cavium,t-adr = <20>; + cavium,t-ce = <60>; + cavium,t-oe = <60>; + cavium,t-we = <45>; + cavium,t-rd-hld = <35>; + cavium,t-wr-hld = <45>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <35>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@4 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <4>; + cavium,t-adr = <320>; + cavium,t-ce = <320>; + cavium,t-oe = <320>; + cavium,t-we = <320>; + cavium,t-rd-hld = <320>; + cavium,t-wr-hld = <320>; + cavium,t-pause = <320>; + cavium,t-wait = <320>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@5 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <5>; + cavium,t-adr = <5>; + cavium,t-ce = <300>; + cavium,t-oe = <125>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <30>; + cavium,t-pause = <0>; + cavium,t-wait = <30>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <16>; + }; + cavium,cs-config@6 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <6>; + cavium,t-adr = <5>; + cavium,t-ce = <300>; + cavium,t-oe = <270>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <70>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,wait-mode; + cavium,bus-width = <16>; + }; + + flash0: nor@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x800000>; + #address-cells = <1>; + #size-cells = <1>; + }; + }; + + dma0: dma-engine@1180000000100 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000100 0x0 0x8>; + interrupts = <0 63>; + }; + + dma1: dma-engine@1180000000108 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000108 0x0 0x8>; + interrupts = <0 63>; + }; + + usbn: usbn@1180068000000 { + compatible = "cavium,octeon-5750-usbn"; + reg = <0x11800 0x68000000 0x0 0x1000>; + ranges; /* Direct mapping */ + #address-cells = <2>; + #size-cells = <2>; + + usbc@16f0010000000 { + compatible = "cavium,octeon-5750-usbc"; + reg = <0x16f00 0x10000000 0x0 0x80000>; + interrupts = <0 56>; + }; + }; + }; +}; -- cgit v1.2.3-59-g8ed1b From 842c1e2c4aaa94ec314d2b0f6595cfb85f42b09d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 8 Mar 2016 23:32:27 +0200 Subject: MIPS: Octeon: Add DTS for EdgeRouter Lite Add DTS for EdgeRouter Lite that is usable as is without any "pruning" with APPENDED_DTB. Compared to builtin generic DTB, we can avoid errors and delays from probing non-existent I2C devices. Signed-off-by: Aaro Koskinen Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts | 59 ++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts (limited to 'arch') diff --git a/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts b/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts new file mode 100644 index 000000000000..243e5dc444fb --- /dev/null +++ b/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts @@ -0,0 +1,59 @@ +/* + * Device tree source for EdgeRouter Lite. + * + * Written by: Aaro Koskinen + * + * 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/ "octeon_3xxx.dtsi" + +/ { + model = "ubnt,e100"; + + soc@0 { + smi0: mdio@1180000001800 { + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c22"; + }; + phy6: ethernet-phy@6 { + reg = <6>; + compatible = "ethernet-phy-ieee802.3-c22"; + }; + phy7: ethernet-phy@7 { + reg = <7>; + compatible = "ethernet-phy-ieee802.3-c22"; + }; + }; + + pip: pip@11800a0000000 { + interface@0 { + ethernet@0 { + phy-handle = <&phy7>; + }; + ethernet@1 { + phy-handle = <&phy6>; + }; + ethernet@2 { + phy-handle = <&phy5>; + }; + }; + }; + + uart0: serial@1180000000800 { + clock-frequency = <500000000>; + }; + + usbn: usbn@1180068000000 { + refclk-frequency = <12000000>; + refclk-type = "crystal"; + }; + }; + + aliases { + pip = &pip; + }; +}; -- cgit v1.2.3-59-g8ed1b From 84f47cf49e3c8348f4a0a04e8fa2404f1e2722cc Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 19 Mar 2016 18:28:51 +0100 Subject: MIPS: Lantiq: Add support for device tree file from boot loader This fetches the device tree file like it is specified in the MIPS UHI interface if one was found. This is also used when the device tree file was appended to the kernel image with cat. This code is copied from arch/mips/bmips/setup.c. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12898/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/prom.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index 297bcaa6b5d3..a5c7fec92a97 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -65,6 +65,8 @@ static void __init prom_init_cmdline(void) void __init plat_mem_setup(void) { + void *dtb; + ioport_resource.start = IOPORT_RESOURCE_START; ioport_resource.end = IOPORT_RESOURCE_END; iomem_resource.start = IOMEM_RESOURCE_START; @@ -72,11 +74,18 @@ void __init plat_mem_setup(void) set_io_port_base((unsigned long) KSEG1); + if (fw_arg0 == -2) /* UHI interface */ + dtb = (void *)fw_arg1; + else if (__dtb_start != __dtb_end) + dtb = (void *)__dtb_start; + else + panic("no dtb found"); + /* - * Load the builtin devicetree. This causes the chosen node to be + * Load the devicetree. This causes the chosen node to be * parsed resulting in our memory appearing */ - __dt_setup_arch(__dtb_start); + __dt_setup_arch(dtb); } void __init device_tree_init(void) -- cgit v1.2.3-59-g8ed1b From e791dfb5fb91c05ce027d147042c5061d0f5cf89 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 19 Mar 2016 18:28:52 +0100 Subject: MIPS: Lantiq: Make it possible to build in no device tree Now it is possible to build in no device tree at all and depend on the boot loader providing one or someone concatenating a device tree to the end of the image. This was copied from arch/mips/bmips/Kconfig Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12899/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/Kconfig | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig index e10d33342b30..177769dbb0e8 100644 --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig @@ -25,7 +25,17 @@ config SOC_FALCON endchoice choice - prompt "Devicetree" + prompt "Built-in device tree" + help + Legacy bootloaders do not pass a DTB pointer to the kernel, so + if a "wrapper" is not being used, the kernel will need to include + a device tree that matches the target board. + + The builtin DTB will only be used if the firmware does not supply + a valid DTB. + +config LANTIQ_DT_NONE + bool "None" config DT_EASY50712 bool "Easy50712" -- cgit v1.2.3-59-g8ed1b From 2cdfec1bbb0a093836f6a471ca15e4e26f8b6401 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:11 +0300 Subject: MIPS: dts: qca: ar9132_tl_wr1043nd_v1.dts: drop unused alias node The TP-LINK TL-WR1043ND board has only one serial port, so replacing the default of 0 with 0 does nothing useful. Moreover, the correct name for aliases node is "aliases" not "alias". An overview of the "aliases" node usage can be found on the device tree usage page at devicetree.org [1]. Also please see chapter 3.3 ("Aliases node") of the ePAPR 1.1 [2]. [1] http://devicetree.org/Device_Tree_Usage#aliases_Node [2] https://www.power.org/documentation/epapr-version-1-1/ Signed-off-by: Antony Pavlov Acked-by: Alban Bedel Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12872/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts index 4f1540e5f963..fb946a13382f 100644 --- a/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts +++ b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts @@ -9,10 +9,6 @@ compatible = "tplink,tl-wr1043nd-v1", "qca,ar9132"; model = "TP-Link TL-WR1043ND Version 1"; - alias { - serial0 = "/ahb/apb/uart@18020000"; - }; - memory@0 { device_type = "memory"; reg = <0x0 0x2000000>; -- cgit v1.2.3-59-g8ed1b From 83fe838466ec9bfcba4f477656cb9a67172d2c29 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:12 +0300 Subject: MIPS: dts: qca: ar9132: use short references for dt nodes Here are some Sascha Hauer's arguments for using aliases in the dts files: - using aliases reduces the number of indentations in dts files; - dts files become independent of the layout of the dtsi files (it becomes possible to introduce another bus {} hierarchy between a toplevel bus and the devices when you have to); - less chances for typos. if &i2c2 does not exist you get an error. If instead you duplicate the whole path in the dts file a typo in the path will just create another node. Signed-off-by: Antony Pavlov Cc: Alban Bedel Cc: Sascha Hauer Cc: Rob Herring Cc: Frank Rowand Cc: Grant Likely Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12873/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/ar9132.dtsi | 8 +- arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts | 94 ++++++++++++------------ 2 files changed, 49 insertions(+), 53 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/ar9132.dtsi b/arch/mips/boot/dts/qca/ar9132.dtsi index 3c2ed9ee5b2f..3bff63b28f54 100644 --- a/arch/mips/boot/dts/qca/ar9132.dtsi +++ b/arch/mips/boot/dts/qca/ar9132.dtsi @@ -52,7 +52,7 @@ #qca,ddr-wb-channel-cells = <1>; }; - uart@18020000 { + uart: uart@18020000 { compatible = "ns8250"; reg = <0x18020000 0x20>; interrupts = <3>; @@ -94,7 +94,7 @@ clock-output-names = "cpu", "ddr", "ahb"; }; - wdt@18060008 { + wdt: wdt@18060008 { compatible = "qca,ar7130-wdt"; reg = <0x18060008 0x8>; @@ -125,7 +125,7 @@ }; }; - usb@1b000100 { + usb: usb@1b000100 { compatible = "qca,ar7100-ehci", "generic-ehci"; reg = <0x1b000100 0x100>; @@ -140,7 +140,7 @@ status = "disabled"; }; - spi@1f000000 { + spi: spi@1f000000 { compatible = "qca,ar9132-spi", "qca,ar7100-spi"; reg = <0x1f000000 0x10>; diff --git a/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts index fb946a13382f..3c3b7ce5737b 100644 --- a/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts +++ b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts @@ -20,55 +20,6 @@ clock-frequency = <40000000>; }; - ahb { - apb { - uart@18020000 { - status = "okay"; - }; - - pll-controller@18050000 { - clocks = <&extosc>; - }; - }; - - usb@1b000100 { - status = "okay"; - }; - - spi@1f000000 { - status = "okay"; - num-cs = <1>; - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "s25sl064a"; - reg = <0>; - spi-max-frequency = <25000000>; - - partition@0 { - label = "u-boot"; - reg = <0x000000 0x020000>; - }; - - partition@1 { - label = "firmware"; - reg = <0x020000 0x7D0000>; - }; - - partition@2 { - label = "art"; - reg = <0x7F0000 0x010000>; - read-only; - }; - }; - }; - }; - - usb-phy { - status = "okay"; - }; - gpio-keys { compatible = "gpio-keys-polled"; #address-cells = <1>; @@ -114,3 +65,48 @@ }; }; }; + +&uart { + status = "okay"; +}; + +&pll { + clocks = <&extosc>; +}; + +&usb { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&spi { + status = "okay"; + num-cs = <1>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25sl064a"; + reg = <0>; + spi-max-frequency = <25000000>; + + partition@0 { + label = "u-boot"; + reg = <0x000000 0x020000>; + }; + + partition@1 { + label = "firmware"; + reg = <0x020000 0x7D0000>; + }; + + partition@2 { + label = "art"; + reg = <0x7F0000 0x010000>; + read-only; + }; + }; +}; -- cgit v1.2.3-59-g8ed1b From af5ad0de22480a452049e0e942b10af77ef60530 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:14 +0300 Subject: MIPS: ath79: Introduce The include/dt-bindings/clock/ath79-clk.h header file is introduced so we can use symbolic identifiers for SoC clocks. Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: Michael Turquette Cc: Stephen Boyd Cc: Rob Herring Cc: linux-mips@linux-mips.org Cc: linux-clk@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12875/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/clock.c | 33 +++++++++++++++++---------------- arch/mips/boot/dts/qca/ar9132.dtsi | 8 +++++--- include/dt-bindings/clock/ath79-clk.h | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 include/dt-bindings/clock/ath79-clk.h (limited to 'arch') diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 618dfd735eed..c3a94ead06ab 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -28,7 +29,7 @@ #define AR71XX_BASE_FREQ 40000000 #define AR724X_BASE_FREQ 40000000 -static struct clk *clks[3]; +static struct clk *clks[ATH79_CLK_END]; static struct clk_onecell_data clk_data = { .clks = clks, .clk_num = ARRAY_SIZE(clks), @@ -78,9 +79,9 @@ static void __init ar71xx_clocks_init(void) ahb_rate = cpu_rate / div; ath79_add_sys_clkdev("ref", ref_rate); - clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -114,9 +115,9 @@ static void __init ar724x_clocks_init(void) ahb_rate = cpu_rate / div; ath79_add_sys_clkdev("ref", ref_rate); - clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -176,9 +177,9 @@ static void __init ar933x_clocks_init(void) } ath79_add_sys_clkdev("ref", ref_rate); - clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -310,9 +311,9 @@ static void __init ar934x_clocks_init(void) ahb_rate = cpu_pll / (postdiv + 1); ath79_add_sys_clkdev("ref", ref_rate); - clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ref", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -397,9 +398,9 @@ static void __init qca955x_clocks_init(void) ahb_rate = cpu_pll / (postdiv + 1); ath79_add_sys_clkdev("ref", ref_rate); - clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ref", NULL); clk_add_alias("uart", NULL, "ref", NULL); diff --git a/arch/mips/boot/dts/qca/ar9132.dtsi b/arch/mips/boot/dts/qca/ar9132.dtsi index 3bff63b28f54..2f9a3eee9fe6 100644 --- a/arch/mips/boot/dts/qca/ar9132.dtsi +++ b/arch/mips/boot/dts/qca/ar9132.dtsi @@ -1,3 +1,5 @@ +#include + / { compatible = "qca,ar9132"; @@ -57,7 +59,7 @@ reg = <0x18020000 0x20>; interrupts = <3>; - clocks = <&pll 2>; + clocks = <&pll ATH79_CLK_AHB>; clock-names = "uart"; reg-io-width = <4>; @@ -100,7 +102,7 @@ interrupts = <4>; - clocks = <&pll 2>; + clocks = <&pll ATH79_CLK_AHB>; clock-names = "wdt"; }; @@ -144,7 +146,7 @@ compatible = "qca,ar9132-spi", "qca,ar7100-spi"; reg = <0x1f000000 0x10>; - clocks = <&pll 2>; + clocks = <&pll ATH79_CLK_AHB>; clock-names = "ahb"; status = "disabled"; diff --git a/include/dt-bindings/clock/ath79-clk.h b/include/dt-bindings/clock/ath79-clk.h new file mode 100644 index 000000000000..27359ad83904 --- /dev/null +++ b/include/dt-bindings/clock/ath79-clk.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014, 2016 Antony Pavlov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __DT_BINDINGS_ATH79_CLK_H +#define __DT_BINDINGS_ATH79_CLK_H + +#define ATH79_CLK_CPU 0 +#define ATH79_CLK_DDR 1 +#define ATH79_CLK_AHB 2 + +#define ATH79_CLK_END 3 + +#endif /* __DT_BINDINGS_ATH79_CLK_H */ -- cgit v1.2.3-59-g8ed1b From 3bdf1071ba7de08c55a5cce54964ded7c0c8540d Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:15 +0300 Subject: MIPS: ath79: update devicetree clock support for AR9132 Current ath79 clock.c code does not read reference clock and pll setup from devicetree. E.g. you can set any clock rate value in board DTS but it will have no effect on the real clk calculation. This patch fixes some AR9132 devicetree clock support defects: * clk initialization function ath79_clocks_init_dt_ng() is introduced; it actually gets pll block base register address and reference clock from devicetree; * pll register parsing code is moved to the separate ar724x_clk_init() function; this function can be called from platform code or from devicetree code. Also mips_hpt_frequency value is set from dt, so the appropriate clock parameter is added to the cpu@0 devicetree node. The same approach can be used for adding AR9331 devicetree support. Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: Michael Turquette Cc: Stephen Boyd Cc: Rob Herring Cc: linux-clk@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12876/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/clock.c | 96 ++++++++++++++++++++++++++++---------- arch/mips/ath79/setup.c | 36 ++++++++++++++ arch/mips/boot/dts/qca/ar9132.dtsi | 1 + 3 files changed, 108 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index c3a94ead06ab..79fb8b44ba09 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -25,6 +27,7 @@ #include #include #include "common.h" +#include "machtypes.h" #define AR71XX_BASE_FREQ 40000000 #define AR724X_BASE_FREQ 40000000 @@ -87,37 +90,48 @@ static void __init ar71xx_clocks_init(void) clk_add_alias("uart", NULL, "ahb", NULL); } -static void __init ar724x_clocks_init(void) +static struct clk * __init ath79_reg_ffclk(const char *name, + const char *parent_name, unsigned int mult, unsigned int div) { - unsigned long ref_rate; - unsigned long cpu_rate; - unsigned long ddr_rate; - unsigned long ahb_rate; - u32 pll; - u32 freq; - u32 div; + struct clk *clk; - ref_rate = AR724X_BASE_FREQ; - pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); + clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); + if (!clk) + panic("failed to allocate %s clock structure", name); - div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); - freq = div * ref_rate; + return clk; +} + +static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base) +{ + u32 pll; + u32 mult, div, ddr_div, ahb_div; + pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG); + + mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; - freq /= div; - cpu_rate = freq; + ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; + ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; - div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; - ddr_rate = freq / div; + clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div); + clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div); + clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div); +} - div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; - ahb_rate = cpu_rate / div; +static void __init ar724x_clocks_init(void) +{ + struct clk *ref_clk; - ath79_add_sys_clkdev("ref", ref_rate); - clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); + ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ); + + ar724x_clk_init(ref_clk, ath79_pll_base); + + /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ + clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); + clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); + clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -420,8 +434,6 @@ void __init ath79_clocks_init(void) qca955x_clocks_init(); else BUG(); - - of_clk_init(NULL); } unsigned long __init @@ -448,8 +460,42 @@ static void __init ath79_clocks_init_dt(struct device_node *np) CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); -CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); + +static void __init ath79_clocks_init_dt_ng(struct device_node *np) +{ + struct clk *ref_clk; + void __iomem *pll_base; + const char *dnfn = of_node_full_name(np); + + ref_clk = of_clk_get(np, 0); + if (IS_ERR(ref_clk)) { + pr_err("%s: of_clk_get failed\n", dnfn); + goto err; + } + + pll_base = of_iomap(np, 0); + if (!pll_base) { + pr_err("%s: can't map pll registers\n", dnfn); + goto err_clk; + } + + ar724x_clk_init(ref_clk, pll_base); + + if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { + pr_err("%s: could not register clk provider\n", dnfn); + goto err_clk; + } + + return; + +err_clk: + clk_put(ref_clk); + +err: + return; +} +CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng); #endif diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 01808e85e263..01af43281bc7 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -222,6 +223,36 @@ void __init plat_mem_setup(void) pm_power_off = ath79_halt; } +static void __init ath79_of_plat_time_init(void) +{ + struct device_node *np; + struct clk *clk; + unsigned long cpu_clk_rate; + + of_clk_init(NULL); + + np = of_get_cpu_node(0, NULL); + if (!np) { + pr_err("Failed to get CPU node\n"); + return; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk)); + return; + } + + cpu_clk_rate = clk_get_rate(clk); + + pr_info("CPU clock: %lu.%03lu MHz\n", + cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000); + + mips_hpt_frequency = cpu_clk_rate / 2; + + clk_put(clk); +} + void __init plat_time_init(void) { unsigned long cpu_clk_rate; @@ -229,6 +260,11 @@ void __init plat_time_init(void) unsigned long ddr_clk_rate; unsigned long ref_clk_rate; + if (IS_ENABLED(CONFIG_OF) && mips_machtype == ATH79_MACH_GENERIC_OF) { + ath79_of_plat_time_init(); + return; + } + ath79_clocks_init(); cpu_clk_rate = ath79_get_sys_clk_rate("cpu"); diff --git a/arch/mips/boot/dts/qca/ar9132.dtsi b/arch/mips/boot/dts/qca/ar9132.dtsi index 2f9a3eee9fe6..302f0a8d2988 100644 --- a/arch/mips/boot/dts/qca/ar9132.dtsi +++ b/arch/mips/boot/dts/qca/ar9132.dtsi @@ -13,6 +13,7 @@ cpu@0 { device_type = "cpu"; compatible = "mips,mips24Kc"; + clocks = <&pll ATH79_CLK_CPU>; reg = <0>; }; }; -- cgit v1.2.3-59-g8ed1b From f4fe969d7f43d92505b09adad2ae93ccaa453ae0 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:16 +0300 Subject: MIPS: ath79: Disable platform code for OF boards. For OF boards we have to skip platform initialization code so we can prove that OF code do all necessary initialization. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Antony Pavlov Signed-off-by: Sudip Mukherjee Reviewed-by: Marek Vasut Cc: Alban Bedel Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12877/ Patchwork: https://patchwork.linux-mips.org/patch/12920/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/setup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 01af43281bc7..7adab180e0ca 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -207,18 +207,20 @@ void __init plat_mem_setup(void) else if (fw_arg0 == -2) __dt_setup_arch((void *)KSEG0ADDR(fw_arg1)); - ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, - AR71XX_RESET_SIZE); - ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, - AR71XX_PLL_SIZE); - ath79_detect_sys_type(); - ath79_ddr_ctrl_init(); - if (mips_machtype != ATH79_MACH_GENERIC_OF) { + ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, + AR71XX_RESET_SIZE); + ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, + AR71XX_PLL_SIZE); + ath79_detect_sys_type(); + ath79_ddr_ctrl_init(); + detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); + /* OF machines should use the reset driver */ _machine_restart = ath79_restart; } + _machine_halt = ath79_halt; pm_power_off = ath79_halt; } -- cgit v1.2.3-59-g8ed1b From 1e6a3492e7bb12aa8ee26050ff6829c39ebaa152 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:17 +0300 Subject: MIPS: dts: qca: introduce AR9331 devicetree This patch introduces devicetree for Atheros AR9331 SoC (AKA Hornet). The AR9331 chip is a Wi-Fi System-On-Chip (WiSOC), typically used in very cheap Access Points and Routers. Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12878/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/ar9331.dtsi | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 arch/mips/boot/dts/qca/ar9331.dtsi (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/ar9331.dtsi b/arch/mips/boot/dts/qca/ar9331.dtsi new file mode 100644 index 000000000000..cf47ed4d8569 --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9331.dtsi @@ -0,0 +1,155 @@ +#include + +/ { + compatible = "qca,ar9331"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips24Kc"; + clocks = <&pll ATH79_CLK_CPU>; + reg = <0>; + }; + }; + + cpuintc: interrupt-controller { + compatible = "qca,ar7100-cpu-intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + qca,ddr-wb-channel-interrupts = <2>, <3>; + qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>; + }; + + ref: ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&cpuintc>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&miscintc>; + + ddr_ctrl: memory-controller@18000000 { + compatible = "qca,ar7240-ddr-controller"; + reg = <0x18000000 0x100>; + + #qca,ddr-wb-channel-cells = <1>; + }; + + uart: uart@18020000 { + compatible = "qca,ar9330-uart"; + reg = <0x18020000 0x14>; + + interrupts = <3>; + + clocks = <&ref>; + clock-names = "uart"; + + status = "disabled"; + }; + + gpio: gpio@18040000 { + compatible = "qca,ar7100-gpio"; + reg = <0x18040000 0x34>; + interrupts = <2>; + + ngpios = <30>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + status = "disabled"; + }; + + pll: pll-controller@18050000 { + compatible = "qca,ar9330-pll"; + reg = <0x18050000 0x100>; + + clocks = <&ref>; + clock-names = "ref"; + + #clock-cells = <1>; + }; + + miscintc: interrupt-controller@18060010 { + compatible = "qca,ar7240-misc-intc"; + reg = <0x18060010 0x4>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + rst: reset-controller@1806001c { + compatible = "qca,ar7100-reset"; + reg = <0x1806001c 0x4>; + + #reset-cells = <1>; + }; + }; + + usb: usb@1b000100 { + compatible = "chipidea,usb2"; + reg = <0x1b000000 0x200>; + + interrupts = <3>; + resets = <&rst 5>; + + phy-names = "usb-phy"; + phys = <&usb_phy>; + + status = "disabled"; + }; + + spi: spi@1f000000 { + compatible = "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + clocks = <&pll ATH79_CLK_AHB>; + clock-names = "ahb"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + usb_phy: usb-phy { + compatible = "qca,ar7100-usb-phy"; + + reset-names = "usb-phy", "usb-suspend-override"; + resets = <&rst 4>, <&rst 3>; + + #phy-cells = <0>; + + status = "disabled"; + }; +}; -- cgit v1.2.3-59-g8ed1b From 5ae5c452e3361612cd8182eb8bdfecf0ebf42288 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:18 +0300 Subject: MIPS: ath79: update devicetree clock support for AR9331 Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: Michael Turquette Cc: Stephen Boyd Cc: Rob Herring Cc: linux-clk@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12879/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/clock.c | 96 +++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 79fb8b44ba09..3cfc5ecddddf 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -137,63 +137,84 @@ static void __init ar724x_clocks_init(void) clk_add_alias("uart", NULL, "ahb", NULL); } -static void __init ar933x_clocks_init(void) +static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base) { - unsigned long ref_rate; - unsigned long cpu_rate; - unsigned long ddr_rate; - unsigned long ahb_rate; u32 clock_ctrl; - u32 cpu_config; - u32 freq; - u32 t; + u32 ref_div; + u32 ninit_mul; + u32 out_div; - t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); - if (t & AR933X_BOOTSTRAP_REF_CLK_40) - ref_rate = (40 * 1000 * 1000); - else - ref_rate = (25 * 1000 * 1000); + u32 cpu_div; + u32 ddr_div; + u32 ahb_div; - clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); + clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG); if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { - cpu_rate = ref_rate; - ahb_rate = ref_rate; - ddr_rate = ref_rate; + ref_div = 1; + ninit_mul = 1; + out_div = 1; + + cpu_div = 1; + ddr_div = 1; + ahb_div = 1; } else { - cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); + u32 cpu_config; + u32 t; + + cpu_config = __raw_readl(pll_base + AR933X_PLL_CPU_CONFIG_REG); t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & AR933X_PLL_CPU_CONFIG_REFDIV_MASK; - freq = ref_rate / t; + ref_div = t; - t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & + ninit_mul = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & AR933X_PLL_CPU_CONFIG_NINT_MASK; - freq *= t; t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; if (t == 0) t = 1; - freq >>= t; + out_div = (1 << t); - t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & + cpu_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; - cpu_rate = freq / t; - t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & + ddr_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; - ddr_rate = freq / t; - t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & + ahb_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; - ahb_rate = freq / t; } - ath79_add_sys_clkdev("ref", ref_rate); - clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", + ninit_mul, ref_div * out_div * cpu_div); + clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", + ninit_mul, ref_div * out_div * ddr_div); + clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", + ninit_mul, ref_div * out_div * ahb_div); +} + +static void __init ar933x_clocks_init(void) +{ + struct clk *ref_clk; + unsigned long ref_rate; + u32 t; + + t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); + if (t & AR933X_BOOTSTRAP_REF_CLK_40) + ref_rate = (40 * 1000 * 1000); + else + ref_rate = (25 * 1000 * 1000); + + ref_clk = ath79_add_sys_clkdev("ref", ref_rate); + + ar9330_clk_init(ref_clk, ath79_pll_base); + + /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ + clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); + clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); + clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -460,7 +481,6 @@ static void __init ath79_clocks_init_dt(struct device_node *np) CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); -CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); @@ -482,7 +502,14 @@ static void __init ath79_clocks_init_dt_ng(struct device_node *np) goto err_clk; } - ar724x_clk_init(ref_clk, pll_base); + if (of_device_is_compatible(np, "qca,ar9130-pll")) + ar724x_clk_init(ref_clk, pll_base); + else if (of_device_is_compatible(np, "qca,ar9330-pll")) + ar9330_clk_init(ref_clk, pll_base); + else { + pr_err("%s: could not find any appropriate clk_init()\n", dnfn); + goto err_clk; + } if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { pr_err("%s: could not register clk provider\n", dnfn); @@ -498,4 +525,5 @@ err: return; } CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng); +CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng); #endif -- cgit v1.2.3-59-g8ed1b From 2c3694d2e6ead3964aafb31e4e529de219ced92b Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:19 +0300 Subject: MIPS: ath79: add initial support for TP-LINK MR3020 The following features are supported: * UART; * SPI-flash; * USB host; * GPIO keys and LEDs. Links: * http://www.tp-link.com/en/products/details/?model=TL-MR3020 * http://wiki.openwrt.org/toh/tp-link/tl-mr3020 * https://wikidevi.com/wiki/TP-LINK_TL-MR3020 Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12880/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/Makefile | 1 + arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts | 118 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile index 14bd22514283..5e2c20d64138 100644 --- a/arch/mips/boot/dts/qca/Makefile +++ b/arch/mips/boot/dts/qca/Makefile @@ -1,5 +1,6 @@ # All DTBs dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb +dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb # Force kbuild to make empty built-in.o if necessary obj- += dummy.o diff --git a/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts b/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts new file mode 100644 index 000000000000..919cf3b854a5 --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +#include +#include + +#include "ar9331.dtsi" + +/ { + model = "TP-Link TL-MR3020"; + compatible = "tplink,tl-mr3020"; + + aliases { + serial0 = &uart; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; + + leds { + compatible = "gpio-leds"; + + wlan { + label = "tp-link:green:wlan"; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + lan { + label = "tp-link:green:lan"; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + wps { + label = "tp-link:green:wps"; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led3g { + label = "tp-link:green:3g"; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + button@0 { + label = "wps"; + linux,code = ; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; + }; + + button@1 { + label = "sw1"; + linux,code = ; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; + }; + + button@2 { + label = "sw2"; + linux,code = ; + gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; + }; + }; + + reg_usb_vbus: reg_usb_vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&ref { + clock-frequency = <25000000>; +}; + +&uart { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&usb { + dr_mode = "host"; + vbus-supply = <®_usb_vbus>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&spi { + num-chipselects = <1>; + status = "okay"; + + /* Spansion S25FL032PIF SPI flash */ + spiflash: s25sl032p@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25sl032p", "jedec,spi-nor"; + spi-max-frequency = <104000000>; + reg = <0>; + }; +}; -- cgit v1.2.3-59-g8ed1b From 3b9ec1b32585438eddd6ec28029fd9620213027d Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:21 +0300 Subject: MIPS: ath79: add initial support for Dragino MS14 (Dragino 2) The following features are supported: * UART; * SPI-flash; * USB host; * GPIO keys and LEDs. Links: * http://www.dragino.com/products/mother-board/item/71-ms14-p.html * https://wiki.openwrt.org/toh/dragino/ms14 Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12882/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/Makefile | 1 + arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts | 102 +++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile index 5e2c20d64138..245136478998 100644 --- a/arch/mips/boot/dts/qca/Makefile +++ b/arch/mips/boot/dts/qca/Makefile @@ -1,5 +1,6 @@ # All DTBs dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb +dtb-$(CONFIG_ATH79) += ar9331_dragino_ms14.dtb dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb # Force kbuild to make empty built-in.o if necessary diff --git a/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts b/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts new file mode 100644 index 000000000000..56f832076a69 --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +#include +#include + +#include "ar9331.dtsi" + +/ { + model = "Dragino MS14 (Dragino 2)"; + compatible = "dragino,ms14"; + + aliases { + serial0 = &uart; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + leds { + compatible = "gpio-leds"; + + wlan { + label = "dragino2:red:wlan"; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + lan { + label = "dragino2:red:lan"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + wan { + label = "dragino2:red:wan"; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + system { + label = "dragino2:red:system"; + gpios = <&gpio 28 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + button@0 { + label = "jumpstart"; + linux,code = ; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&ref { + clock-frequency = <25000000>; +}; + +&uart { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&usb { + dr_mode = "host"; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&spi { + num-chipselects = <1>; + status = "okay"; + + /* Winbond 25Q128BVFG SPI flash */ + spiflash: w25q128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "winbond,w25q128", "jedec,spi-nor"; + spi-max-frequency = <104000000>; + reg = <0>; + }; +}; -- cgit v1.2.3-59-g8ed1b From 930c54ff39fcbe988c2eecf1ae52764c780fe893 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:23 +0300 Subject: MIPS: ath79: add initial support for Onion Omega The following features are supported: * UART; * SPI-flash; * USB host; * GPIO key and LED. Please see https://onion.io/omega for details. Signed-off-by: Antony Pavlov Cc: Gabor Juhos Cc: Alban Bedel Cc: L. D. Pinney Cc: Boken Lin Cc: Jacky Huang Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12884/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/Makefile | 1 + arch/mips/boot/dts/qca/ar9331_omega.dts | 78 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 arch/mips/boot/dts/qca/ar9331_omega.dts (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile index 245136478998..dc0b5a4071c4 100644 --- a/arch/mips/boot/dts/qca/Makefile +++ b/arch/mips/boot/dts/qca/Makefile @@ -1,6 +1,7 @@ # All DTBs dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb dtb-$(CONFIG_ATH79) += ar9331_dragino_ms14.dtb +dtb-$(CONFIG_ATH79) += ar9331_omega.dtb dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb # Force kbuild to make empty built-in.o if necessary diff --git a/arch/mips/boot/dts/qca/ar9331_omega.dts b/arch/mips/boot/dts/qca/ar9331_omega.dts new file mode 100644 index 000000000000..b2be3b04479d --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9331_omega.dts @@ -0,0 +1,78 @@ +/dts-v1/; + +#include +#include + +#include "ar9331.dtsi" + +/ { + model = "Onion Omega"; + compatible = "onion,omega"; + + aliases { + serial0 = &uart; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + leds { + compatible = "gpio-leds"; + + system { + label = "onion:amber:system"; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + button@0 { + label = "reset"; + linux,code = ; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&ref { + clock-frequency = <25000000>; +}; + +&uart { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&usb { + dr_mode = "host"; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&spi { + num-chipselects = <1>; + status = "okay"; + + /* Winbond 25Q128FVSG SPI flash */ + spiflash: w25q128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "winbond,w25q128", "jedec,spi-nor"; + spi-max-frequency = <104000000>; + reg = <0>; + }; +}; -- cgit v1.2.3-59-g8ed1b From 98c1c5078deba1feb9c040eb7708a299e41a8d84 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 17 Mar 2016 06:34:25 +0300 Subject: MIPS: ath79: add initial support for DPT-Module The following features are supported: * UART; * SPI-flash; * USB host; * GPIO key and LED. Links: * https://dptechnics.com/shop/index.php?route=product/product&path=59&product_id=50 * https://dptechnics.com/shop/index.php?route=product/product&path=59&product_id=63 Signed-off-by: Antony Pavlov Cc: Daan Pape Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12886/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/qca/Makefile | 1 + arch/mips/boot/dts/qca/ar9331_dpt_module.dts | 78 ++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 arch/mips/boot/dts/qca/ar9331_dpt_module.dts (limited to 'arch') diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile index dc0b5a4071c4..63a9ddf048c9 100644 --- a/arch/mips/boot/dts/qca/Makefile +++ b/arch/mips/boot/dts/qca/Makefile @@ -1,5 +1,6 @@ # All DTBs dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb +dtb-$(CONFIG_ATH79) += ar9331_dpt_module.dtb dtb-$(CONFIG_ATH79) += ar9331_dragino_ms14.dtb dtb-$(CONFIG_ATH79) += ar9331_omega.dtb dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb diff --git a/arch/mips/boot/dts/qca/ar9331_dpt_module.dts b/arch/mips/boot/dts/qca/ar9331_dpt_module.dts new file mode 100644 index 000000000000..98e74500e79d --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9331_dpt_module.dts @@ -0,0 +1,78 @@ +/dts-v1/; + +#include +#include + +#include "ar9331.dtsi" + +/ { + model = "DPTechnics DPT-Module"; + compatible = "dptechnics,dpt-module"; + + aliases { + serial0 = &uart; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + leds { + compatible = "gpio-leds"; + + system { + label = "dpt-module:green:system"; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + button@0 { + label = "reset"; + linux,code = ; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&ref { + clock-frequency = <25000000>; +}; + +&uart { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&usb { + dr_mode = "host"; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&spi { + num-chipselects = <1>; + status = "okay"; + + /* Winbond 25Q128FVSG SPI flash */ + spiflash: w25q128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "winbond,w25q128", "jedec,spi-nor"; + spi-max-frequency = <104000000>; + reg = <0>; + }; +}; -- cgit v1.2.3-59-g8ed1b From f270d881fa552c9c21c37417af2bf95da9a74347 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:21 +0000 Subject: MIPS: Detect MIPSr6 Virtual Processor support MIPSr6 introduces support for "Virtual Processors", which are conceptually similar to VPEs from the now-deprecated MT ASE. Detect whether the system supports VPs using the VP bit in Config5, adding cpu_has_vp for use by later patches. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Maciej W. Rozycki Cc: Joshua Kinard Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12327/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 1 + arch/mips/kernel/cpu-probe.c | 2 ++ 4 files changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index eeec8c8e2da2..57cdc5be9545 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -311,6 +311,10 @@ #define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) #endif +#ifndef cpu_has_vp +#define cpu_has_vp (cpu_data[0].options & MIPS_CPU_VP) +#endif + #ifndef cpu_has_userlocal #define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 7bea0f3bf9ee..631aa10fdebe 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -390,6 +390,7 @@ enum cpu_type_enum { #define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ #define MIPS_CPU_NAN_LEGACY 0x40000000000ull /* Legacy NaN implemented */ #define MIPS_CPU_NAN_2008 0x80000000000ull /* 2008 NaN implemented */ +#define MIPS_CPU_VP 0x100000000000ull /* MIPSr6 Virtual Processors (multi-threading) */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 3ad19ad04d8a..ca251f6fea8e 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -623,6 +623,7 @@ #define MIPS_CONF5_MRP (_ULCAST_(1) << 3) #define MIPS_CONF5_LLB (_ULCAST_(1) << 4) #define MIPS_CONF5_MVH (_ULCAST_(1) << 5) +#define MIPS_CONF5_VP (_ULCAST_(1) << 7) #define MIPS_CONF5_FRE (_ULCAST_(1) << 8) #define MIPS_CONF5_UFE (_ULCAST_(1) << 9) #define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 9ad6157e23de..e0cfa3b85bca 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -796,6 +796,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c) if (config5 & MIPS_CONF5_MVH) c->options |= MIPS_CPU_XPA; #endif + if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP)) + c->options |= MIPS_CPU_VP; return config5 & MIPS_CONF_M; } -- cgit v1.2.3-59-g8ed1b From 04d83f948510f17f8f2ab320b2386f4b5fbd0bd4 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Feb 2016 03:15:22 +0000 Subject: MIPS: traps: Make sure secondary cores have a sane ebase register We shouldn't trust that the secondary cores will have a sane ebase register (either from the bootloader or during the hardware design phase) so use the ebase address as calculated by the boot CPU. Signed-off-by: Markos Chandras Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: James Hogan Cc: Petri Gynther Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12328/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 82c2fcf7e585..bd4893feffa6 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2116,6 +2116,13 @@ void per_cpu_trap_init(bool is_boot_cpu) * o read IntCtl.IPFDC to determine the fast debug channel interrupt */ if (cpu_has_mips_r2_r6) { + /* + * We shouldn't trust a secondary core has a sane EBASE register + * so use the one calculated by the boot CPU. + */ + if (!is_boot_cpu) + write_c0_ebase(ebase); + cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP; cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7; cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7; -- cgit v1.2.3-59-g8ed1b From 0f2a1484487407390196ca5b3c3a07bee6df15ad Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Feb 2016 03:15:23 +0000 Subject: MIPS: pm-cps: Avoid offset overflow on MIPSr6 This is similar to commit 934c79231c1b ("MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions"). The CACHE instruction has been redefined for MIPSr6 and it reduced its offset field to 8 bits. This leads to micro-assembler field overflow warnings when booting SMP MIPSr6 cores like the following one: Call Trace: [] show_stack+0x68/0x88 [] dump_stack+0x68/0x88 [] warn_slowpath_common+0x8c/0xc8 [] warn_slowpath_fmt+0x38/0x48 [] build_insn+0x514/0x5c0 [] cps_gen_cache_routine.isra.3+0xe0/0x1b8 [] cps_pm_init+0x364/0x9ec [] do_one_initcall+0x90/0x1a8 [] kernel_init_freeable+0x160/0x21c [] kernel_init+0x10/0xf8 [] ret_from_kernel_thread+0x14/0x1c We fix this by incrementing the base register on every loop. Signed-off-by: Markos Chandras Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12329/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/pm-cps.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index fa3f9ebad8f4..adda3ffb9b78 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -224,11 +224,18 @@ static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl, uasm_build_label(pl, *pp, lbl); /* Generate the cache ops */ - for (i = 0; i < unroll_lines; i++) - uasm_i_cache(pp, op, i * cache->linesz, t0); + for (i = 0; i < unroll_lines; i++) { + if (cpu_has_mips_r6) { + uasm_i_cache(pp, op, 0, t0); + uasm_i_addiu(pp, t0, t0, cache->linesz); + } else { + uasm_i_cache(pp, op, i * cache->linesz, t0); + } + } - /* Update the base address */ - uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz); + if (!cpu_has_mips_r6) + /* Update the base address */ + uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz); /* Loop if we haven't reached the end address yet */ uasm_il_bne(pp, pr, t0, t1, lbl); -- cgit v1.2.3-59-g8ed1b From 88036557bac3c831a564dcd6c860da48ae55756f Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Feb 2016 03:15:24 +0000 Subject: MIPS: CPC: Add start, stop and running CM3 CPC registers Add the new CM3 registers for controlling bringing up and powering down VPs on MIPSR6 cores. Signed-off-by: Markos Chandras Signed-off-by: Paul Burton Cc: Bjorn Helgaas Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12330/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cpc.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index e09035239e53..8c519f9827a3 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h @@ -106,6 +106,9 @@ BUILD_CPC_R_(revision, MIPS_CPC_GCB_OFS + 0x20) BUILD_CPC_Cx_RW(cmd, 0x00) BUILD_CPC_Cx_RW(stat_conf, 0x08) BUILD_CPC_Cx_RW(other, 0x10) +BUILD_CPC_Cx_RW(vp_stop, 0x20) +BUILD_CPC_Cx_RW(vp_run, 0x28) +BUILD_CPC_Cx_RW(vp_running, 0x30) /* CPC_Cx_CMD register fields */ #define CPC_Cx_CMD_SHF 0 -- cgit v1.2.3-59-g8ed1b From db8e00af7b4a09ef5924140c1c42494fc88204ef Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:25 +0000 Subject: MIPS: CM: Add CM GCR_BEV_BASE accessors Generate accessor functions for the GCR_BEV_BASE register introduced by CM3, for use by a later patch. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12331/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 4ac8e4b69fb5..b79433f19b77 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -208,6 +208,7 @@ BUILD_CM_RW(l2_config, MIPS_CM_GCB_OFS + 0x130) BUILD_CM_RW(sys_config2, MIPS_CM_GCB_OFS + 0x150) BUILD_CM_RW(l2_pft_control, MIPS_CM_GCB_OFS + 0x300) BUILD_CM_RW(l2_pft_control_b, MIPS_CM_GCB_OFS + 0x308) +BUILD_CM_RW(bev_base, MIPS_CM_GCB_OFS + 0x680) /* Core Local & Core Other register accessor functions */ BUILD_CM_Cx_RW(reset_release, 0x00) -- cgit v1.2.3-59-g8ed1b From a60ae81e5e5918138703f22427dd8f2445985b55 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:26 +0000 Subject: MIPS: CM: Fix mips_cm_max_vp_width for UP kernels Fix mips_cm_max_vp_width for UP kernels where it previously referenced smp_num_siblings, which is not declared for UP kernels. This led to build errors such as the following: drivers/built-in.o: In function `$L446': irq-mips-gic.c:(.text+0x1994): undefined reference to `smp_num_siblings' drivers/built-in.o:irq-mips-gic.c:(.text+0x199c): more undefined references to `smp_num_siblings' follow On UP kernels simply return 1, leaving the reference to smp_num_siblings in place only for SMP kernels. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12332/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index b79433f19b77..3fea29e50c46 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -462,7 +462,10 @@ static inline unsigned int mips_cm_max_vp_width(void) if (mips_cm_revision() >= CM_REV_CM3) return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK; - return smp_num_siblings; + if (config_enabled(CONFIG_SMP)) + return smp_num_siblings; + + return 1; } /** -- cgit v1.2.3-59-g8ed1b From ba1c0a490a1fa61971b1cf9dd89acc7b4424e798 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:29 +0000 Subject: MIPS: smp-cps: Ensure our VP ident calculation is correct When bringing up a CPU, ensure that its local ID as provided by the GIC matches up with our calculation of it. This is vital, since if the condition doesn't hold then we won't have configured interrupts correctly for the VP. Signed-off-by: Paul Burton Cc: Rusty Russell Cc: Matt Redfearn Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12335/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-cps.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 253e1409338c..9d9c7ff61d4d 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -307,6 +307,17 @@ static void cps_init_secondary(void) if (cpu_has_mipsmt) dmt(); + if (mips_cm_revision() >= CM_REV_CM3) { + unsigned ident = gic_read_local_vp_id(); + + /* + * Ensure that our calculation of the VP ID matches up with + * what the GIC reports, otherwise we'll have configured + * interrupts incorrectly. + */ + BUG_ON(ident != mips_cm_vp_id(smp_processor_id())); + } + change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7); } -- cgit v1.2.3-59-g8ed1b From 3dbc9971618ba0e88f25f2168aa5731b53af6f0b Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:30 +0000 Subject: MIPS: smp-cps: Pull cache init into a function In preparation for further modifications to mips_cps_core_entry, pull the L1 cache initialisation out into a separate function. This both makes the code in mips_cps_core_entry read more clearly, particularly when modifying it, and shortens it which will become important as code is added that needs to continue to fit within the reset vector. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12336/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 143 ++++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 67 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index ac81edd44563..8d5ea4b778f9 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -90,74 +90,9 @@ not_nmi: li t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS mtc0 t0, CP0_STATUS - /* - * Clear the bits used to index the caches. Note that the architecture - * dictates that writing to any of TagLo or TagHi selects 0 or 2 should - * be valid for all MIPS32 CPUs, even those for which said writes are - * unnecessary. - */ - mtc0 zero, CP0_TAGLO, 0 - mtc0 zero, CP0_TAGHI, 0 - mtc0 zero, CP0_TAGLO, 2 - mtc0 zero, CP0_TAGHI, 2 - ehb - - /* Primary cache configuration is indicated by Config1 */ - mfc0 v0, CP0_CONFIG, 1 - - /* Detect I-cache line size */ - _EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ - beqz t0, icache_done - li t1, 2 - sllv t0, t1, t0 - - /* Detect I-cache size */ - _EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ - xori t2, t1, 0x7 - beqz t2, 1f - li t3, 32 - addiu t1, t1, 1 - sllv t1, t3, t1 -1: /* At this point t1 == I-cache sets per way */ - _EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ - addiu t2, t2, 1 - mul t1, t1, t0 - mul t1, t1, t2 - - li a0, CKSEG0 - PTR_ADD a1, a0, t1 -1: cache Index_Store_Tag_I, 0(a0) - PTR_ADD a0, a0, t0 - bne a0, a1, 1b + /* Initialize the L1 caches */ + jal mips_cps_cache_init nop -icache_done: - - /* Detect D-cache line size */ - _EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ - beqz t0, dcache_done - li t1, 2 - sllv t0, t1, t0 - - /* Detect D-cache size */ - _EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ - xori t2, t1, 0x7 - beqz t2, 1f - li t3, 32 - addiu t1, t1, 1 - sllv t1, t3, t1 -1: /* At this point t1 == D-cache sets per way */ - _EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ - addiu t2, t2, 1 - mul t1, t1, t0 - mul t1, t1, t2 - - li a0, CKSEG0 - PTR_ADDU a1, a0, t1 - PTR_SUBU a1, a1, t0 -1: cache Index_Store_Tag_D, 0(a0) - bne a0, a1, 1b - PTR_ADD a0, a0, t0 -dcache_done: /* Set Kseg0 CCA to that in s0 */ mfc0 t0, CP0_CONFIG @@ -486,6 +421,80 @@ LEAF(mips_cps_boot_vpes) nop END(mips_cps_boot_vpes) +LEAF(mips_cps_cache_init) + /* + * Clear the bits used to index the caches. Note that the architecture + * dictates that writing to any of TagLo or TagHi selects 0 or 2 should + * be valid for all MIPS32 CPUs, even those for which said writes are + * unnecessary. + */ + mtc0 zero, CP0_TAGLO, 0 + mtc0 zero, CP0_TAGHI, 0 + mtc0 zero, CP0_TAGLO, 2 + mtc0 zero, CP0_TAGHI, 2 + ehb + + /* Primary cache configuration is indicated by Config1 */ + mfc0 v0, CP0_CONFIG, 1 + + /* Detect I-cache line size */ + _EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ + beqz t0, icache_done + li t1, 2 + sllv t0, t1, t0 + + /* Detect I-cache size */ + _EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ + xori t2, t1, 0x7 + beqz t2, 1f + li t3, 32 + addiu t1, t1, 1 + sllv t1, t3, t1 +1: /* At this point t1 == I-cache sets per way */ + _EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ + addiu t2, t2, 1 + mul t1, t1, t0 + mul t1, t1, t2 + + li a0, CKSEG0 + PTR_ADD a1, a0, t1 +1: cache Index_Store_Tag_I, 0(a0) + PTR_ADD a0, a0, t0 + bne a0, a1, 1b + nop +icache_done: + + /* Detect D-cache line size */ + _EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ + beqz t0, dcache_done + li t1, 2 + sllv t0, t1, t0 + + /* Detect D-cache size */ + _EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ + xori t2, t1, 0x7 + beqz t2, 1f + li t3, 32 + addiu t1, t1, 1 + sllv t1, t3, t1 +1: /* At this point t1 == D-cache sets per way */ + _EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ + addiu t2, t2, 1 + mul t1, t1, t0 + mul t1, t1, t2 + + li a0, CKSEG0 + PTR_ADDU a1, a0, t1 + PTR_SUBU a1, a1, t0 +1: cache Index_Store_Tag_D, 0(a0) + bne a0, a1, 1b + PTR_ADD a0, a0, t0 +dcache_done: + + jr ra + nop + END(mips_cps_cache_init) + #if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM) /* Calculate a pointer to this CPUs struct mips_static_suspend_state */ -- cgit v1.2.3-59-g8ed1b From f12401d7219f5a1e361ded834016e5777a10262b Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:31 +0000 Subject: MIPS: smp-cps: Pull boot config retrieval out of mips_cps_boot_vpes The mips_cps_boot_vpes function previously included code to retrieve pointers to the core & VPE boot configuration structs. These structures were used both by mips_cps_boot_vpes and by its mips_cps_core_entry callsite. In preparation for skipping the call to mips_cps_boot_vpes on some invocations of mips_cps_core_entry, pull the calculation of those pointers out into a separate function such that it can continue to be shared. Signed-off-by: Paul Burton Cc: Rusty Russell Cc: Matt Redfearn Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12337/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/smp-cps.h | 2 +- arch/mips/kernel/cps-vec.S | 74 +++++++++++++++++++++++++---------------- arch/mips/kernel/smp-cps.c | 7 ++-- 3 files changed, 52 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index 326c16ebd589..2ae1f61a4a95 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -29,7 +29,7 @@ extern struct core_boot_config *mips_cps_core_bootcfg; extern void mips_cps_core_entry(void); extern void mips_cps_core_init(void); -extern struct vpe_boot_config *mips_cps_boot_vpes(void); +extern void mips_cps_boot_vpes(struct core_boot_config *cfg, unsigned vpe); extern void mips_cps_pm_save(void); extern void mips_cps_pm_restore(void); diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 8d5ea4b778f9..2613de9bcb2d 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -60,6 +60,17 @@ nop .endm + /* Calculate an uncached address for the CM GCRs */ + .macro cmgcrb dest + .set push + .set noat + MFC0 $1, CP0_CMGCRBASE + PTR_SLL $1, $1, 4 + PTR_LI \dest, UNCAC_BASE + PTR_ADDU \dest, \dest, $1 + .set pop + .endm + .section .text.cps-vec .balign 0x1000 @@ -102,13 +113,8 @@ not_nmi: mtc0 t0, CP0_CONFIG ehb - /* Calculate an uncached address for the CM GCRs */ - MFC0 v1, CP0_CMGCRBASE - PTR_SLL v1, v1, 4 - PTR_LI t0, UNCAC_BASE - PTR_ADDU v1, v1, t0 - /* Enter the coherent domain */ + cmgcrb v1 li t0, 0xff sw t0, GCR_CL_COHERENCE_OFS(v1) ehb @@ -128,17 +134,22 @@ not_nmi: /* Do any EVA initialization if necessary */ eva_init + /* Retrieve boot configuration pointers */ + jal mips_cps_get_bootcfg + nop + /* * Boot any other VPEs within this core that should be online, and * deactivate this VPE if it should be offline. */ + move a1, t9 jal mips_cps_boot_vpes - nop + move a0, v0 /* Off we go! */ - PTR_L t1, VPEBOOTCFG_PC(v0) - PTR_L gp, VPEBOOTCFG_GP(v0) - PTR_L sp, VPEBOOTCFG_SP(v0) + PTR_L t1, VPEBOOTCFG_PC(v1) + PTR_L gp, VPEBOOTCFG_GP(v1) + PTR_L sp, VPEBOOTCFG_SP(v1) jr t1 nop END(mips_cps_core_entry) @@ -258,18 +269,21 @@ LEAF(mips_cps_core_init) nop END(mips_cps_core_init) -LEAF(mips_cps_boot_vpes) - /* Retrieve CM base address */ - PTR_LA t0, mips_cm_base - PTR_L t0, 0(t0) - +/** + * mips_cps_get_bootcfg() - retrieve boot configuration pointers + * + * Returns: pointer to struct core_boot_config in v0, pointer to + * struct vpe_boot_config in v1, VPE ID in t9 + */ +LEAF(mips_cps_get_bootcfg) /* Calculate a pointer to this cores struct core_boot_config */ + cmgcrb t0 lw t0, GCR_CL_ID_OFS(t0) li t1, COREBOOTCFG_SIZE mul t0, t0, t1 PTR_LA t1, mips_cps_core_bootcfg PTR_L t1, 0(t1) - PTR_ADDU t0, t0, t1 + PTR_ADDU v0, t0, t1 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ li t9, 0 @@ -297,22 +311,27 @@ LEAF(mips_cps_boot_vpes) 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ li t1, VPEBOOTCFG_SIZE - mul v0, t9, t1 - PTR_L ta3, COREBOOTCFG_VPECONFIG(t0) - PTR_ADDU v0, v0, ta3 - -#ifdef CONFIG_MIPS_MT_SMP + mul v1, t9, t1 + PTR_L ta3, COREBOOTCFG_VPECONFIG(v0) + PTR_ADDU v1, v1, ta3 - /* If the core doesn't support MT then return */ - bnez ta2, 1f - nop jr ra nop + END(mips_cps_get_bootcfg) + +LEAF(mips_cps_boot_vpes) + PTR_L ta2, COREBOOTCFG_VPEMASK(a0) + PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) + +#ifdef CONFIG_MIPS_MT .set push .set mt -1: /* Enter VPE configuration state */ + /* If the core doesn't support MT then return */ + has_mt t0, 5f + + /* Enter VPE configuration state */ dvpe PTR_LA t1, 1f jr.hb t1 @@ -323,7 +342,6 @@ LEAF(mips_cps_boot_vpes) ehb /* Loop through each VPE */ - PTR_L ta2, COREBOOTCFG_VPEMASK(t0) move t8, ta2 li ta1, 0 @@ -400,7 +418,7 @@ LEAF(mips_cps_boot_vpes) /* Check whether this VPE is meant to be running */ li t0, 1 - sll t0, t0, t9 + sll t0, t0, a1 and t0, t0, t8 bnez t0, 2f nop @@ -417,7 +435,7 @@ LEAF(mips_cps_boot_vpes) #endif /* CONFIG_MIPS_MT_SMP */ /* Return */ - jr ra +5: jr ra nop END(mips_cps_boot_vpes) diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 9d9c7ff61d4d..1a289db642cf 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -250,7 +250,10 @@ static void boot_core(unsigned core) static void remote_vpe_boot(void *dummy) { - mips_cps_boot_vpes(); + unsigned core = current_cpu_data.core; + struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; + + mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_cpu_data)); } static void cps_boot_secondary(int cpu, struct task_struct *idle) @@ -296,7 +299,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) BUG_ON(!cpu_has_mipsmt); /* Boot a VPE on this core */ - mips_cps_boot_vpes(); + mips_cps_boot_vpes(core_cfg, vpe_id); out: preempt_enable(); } -- cgit v1.2.3-59-g8ed1b From 87a70bcdb41008decfcf7c217e26b0bcd7f52642 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:32 +0000 Subject: MIPS: smp-cps: Skip core setup if coherent In preparation for supporting MIPSr6 multithreading (ie. VPs) which will begin execution from the core reset vector, skip core level setup if the core is already coherent. This is never the case when a core is first started, since boot_core explicitly clears the cores GCR_Cx_COH_EN register, and always the case when secondary VPs start since the first VP to start will have enabled coherence after initialising the core & its caches. One notable side effect of this patch is that eva_init gets called slightly earlier, prior to mips_cps_core_init rather than after it. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12338/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 2613de9bcb2d..4849cbd47ccc 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -101,43 +101,52 @@ not_nmi: li t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS mtc0 t0, CP0_STATUS + /* Skip cache & coherence setup if we're already coherent */ + cmgcrb v1 + lw s7, GCR_CL_COHERENCE_OFS(v1) + bnez s7, 1f + nop + /* Initialize the L1 caches */ jal mips_cps_cache_init nop + /* Enter the coherent domain */ + li t0, 0xff + sw t0, GCR_CL_COHERENCE_OFS(v1) + ehb + /* Set Kseg0 CCA to that in s0 */ - mfc0 t0, CP0_CONFIG +1: mfc0 t0, CP0_CONFIG ori t0, 0x7 xori t0, 0x7 or t0, t0, s0 mtc0 t0, CP0_CONFIG ehb - /* Enter the coherent domain */ - cmgcrb v1 - li t0, 0xff - sw t0, GCR_CL_COHERENCE_OFS(v1) - ehb - /* Jump to kseg0 */ PTR_LA t0, 1f jr t0 nop /* - * We're up, cached & coherent. Perform any further required core-level - * initialisation. + * We're up, cached & coherent. Perform any EVA initialization necessary + * before we access memory. */ -1: jal mips_cps_core_init - nop - - /* Do any EVA initialization if necessary */ - eva_init +1: eva_init /* Retrieve boot configuration pointers */ jal mips_cps_get_bootcfg nop + /* Skip core-level init if we started up coherent */ + bnez s7, 1f + nop + + /* Perform any further required core-level initialisation */ + jal mips_cps_core_init + nop + /* * Boot any other VPEs within this core that should be online, and * deactivate this VPE if it should be offline. @@ -147,7 +156,7 @@ not_nmi: move a0, v0 /* Off we go! */ - PTR_L t1, VPEBOOTCFG_PC(v1) +1: PTR_L t1, VPEBOOTCFG_PC(v1) PTR_L gp, VPEBOOTCFG_GP(v1) PTR_L sp, VPEBOOTCFG_SP(v1) jr t1 -- cgit v1.2.3-59-g8ed1b From 5a3e7c02d84fd31e6a2b1b242612363b6131a09e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:33 +0000 Subject: MIPS: smp-cps: Support MIPSr6 Virtual Processors Introduce support for bringing up Virtual Processors in MIPSr6 systems as CPUs, much like their VPE parallel from the now-deprecated MT ASE. The existing mips_cps_boot_vpes function fits the MIPSr6 architecture pretty well - it can now simply write the mask of running VPs to the VC_RUN register, rather than looping through each & starting or stopping as appropriate as is done for VPEs from the MT ASE. Thus the VP support is in general an extension & simplification of the existing MT ASE VPE (aka SMVP) support. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Rusty Russell Cc: Maciej W. Rozycki Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12339/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/cpu-info.h | 4 +-- arch/mips/kernel/cps-vec.S | 53 ++++++++++++++++++++++++++++++++++++++-- arch/mips/kernel/smp-cps.c | 35 +++++++++++++++++++++++--- 4 files changed, 85 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 882e73c3334e..e77a439c1932 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2282,7 +2282,7 @@ config MIPS_CMP config MIPS_CPS bool "MIPS Coherent Processing System support" - depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6 + depends on SYS_SUPPORTS_MIPS_CPS select MIPS_CM select MIPS_CPC select MIPS_CPS_PM if HOTPLUG_CPU diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index af12c1f9f1a8..9ec81684b1b8 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -68,7 +68,7 @@ struct cpuinfo_mips { #ifdef CONFIG_64BIT int vmbits; /* Virtual memory size in bits */ #endif -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) /* * There is not necessarily a 1:1 mapping of VPE num to CPU number * in particular on multi-core systems. @@ -125,7 +125,7 @@ struct proc_cpuinfo_notifier_args { unsigned long n; }; -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) # define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id) #else # define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; }) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 4849cbd47ccc..c28138d53d32 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -18,9 +18,12 @@ #include #include +#define GCR_CPC_BASE_OFS 0x0088 #define GCR_CL_COHERENCE_OFS 0x2008 #define GCR_CL_ID_OFS 0x2028 +#define CPC_CL_VC_RUN_OFS 0x2028 + .extern mips_cm_base .set noreorder @@ -60,6 +63,26 @@ nop .endm + /* + * Set dest to non-zero if the core supports MIPSr6 multithreading + * (ie. VPs), else zero. If MIPSr6 multithreading is not supported then + * branch to nomt. + */ + .macro has_vp dest, nomt + mfc0 \dest, CP0_CONFIG, 1 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 2 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 3 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 4 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 5 + andi \dest, \dest, MIPS_CONF5_VP + beqz \dest, \nomt + nop + .endm + /* Calculate an uncached address for the CM GCRs */ .macro cmgcrb dest .set push @@ -296,7 +319,17 @@ LEAF(mips_cps_get_bootcfg) /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ li t9, 0 -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_CPU_MIPSR6) + has_vp ta2, 1f + + /* + * Assume non-contiguous numbering. Perhaps some day we'll need + * to handle contiguous VP numbering, but no such systems yet + * exist. + */ + mfc0 t9, $3, 1 + andi t9, t9, 0xff +#elif defined(CONFIG_MIPS_MT_SMP) has_mt ta2, 1f /* Find the number of VPEs present in the core */ @@ -332,7 +365,23 @@ LEAF(mips_cps_boot_vpes) PTR_L ta2, COREBOOTCFG_VPEMASK(a0) PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) -#ifdef CONFIG_MIPS_MT +#if defined(CONFIG_CPU_MIPSR6) + + has_vp t0, 5f + + /* Find base address of CPC */ + cmgcrb t3 + PTR_L t1, GCR_CPC_BASE_OFS(t3) + PTR_LI t2, ~0x7fff + and t1, t1, t2 + PTR_LI t2, UNCAC_BASE + PTR_ADD t1, t1, t2 + + /* Set VC_RUN to the VPE mask */ + PTR_S ta2, CPC_CL_VC_RUN_OFS(t1) + ehb + +#elif defined(CONFIG_MIPS_MT) .set push .set mt diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 1a289db642cf..06512171fd19 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -35,7 +35,8 @@ static unsigned core_vpe_count(unsigned core) { unsigned cfg; - if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp)) return 1; mips_cm_lock_other(core, 0); @@ -47,11 +48,12 @@ static unsigned core_vpe_count(unsigned core) static void __init cps_smp_setup(void) { unsigned int ncores, nvpes, core_vpes; + unsigned long core_entry; int c, v; /* Detect & record VPE topology */ ncores = mips_cm_numcores(); - pr_info("VPE topology "); + pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE"); for (c = nvpes = 0; c < ncores; c++) { core_vpes = core_vpe_count(c); pr_cont("%c%u", c ? ',' : '{', core_vpes); @@ -62,7 +64,7 @@ static void __init cps_smp_setup(void) for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) { cpu_data[nvpes + v].core = c; -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) cpu_data[nvpes + v].vpe_id = v; #endif } @@ -91,6 +93,11 @@ static void __init cps_smp_setup(void) /* Make core 0 coherent with everything */ write_gcr_cl_coherence(0xff); + if (mips_cm_revision() >= CM_REV_CM3) { + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_bev_base(core_entry); + } + #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ if (cpu_has_fpu) @@ -213,6 +220,18 @@ static void boot_core(unsigned core) if (mips_cpc_present()) { /* Reset the core */ mips_cpc_lock_other(core); + + if (mips_cm_revision() >= CM_REV_CM3) { + /* Run VP0 following the reset */ + write_cpc_co_vp_run(0x1); + + /* + * Ensure that the VP_RUN register is written before the + * core leaves reset. + */ + wmb(); + } + write_cpc_co_cmd(CPC_Cx_CMD_RESET); timeout = 100; @@ -262,6 +281,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id]; + unsigned long core_entry; unsigned int remote; int err; @@ -279,6 +299,13 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } + if (cpu_has_vp) { + mips_cm_lock_other(core, vpe_id); + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_co_reset_base(core_entry); + mips_cm_unlock_other(); + } + if (core != current_cpu_data.core) { /* Boot a VPE on another powered up core */ for (remote = 0; remote < NR_CPUS; remote++) { @@ -296,7 +323,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } - BUG_ON(!cpu_has_mipsmt); + BUG_ON(!cpu_has_mipsmt && !cpu_has_vp); /* Boot a VPE on this core */ mips_cps_boot_vpes(core_cfg, vpe_id); -- cgit v1.2.3-59-g8ed1b From 6422a913856716be080dba4c2cb9d083d4e244ed Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:34 +0000 Subject: MIPS: smp-cps: Add nothreads kernel parameter When debugging a new system or core it can be useful to disable the use of multithreading. Introduce a "nothreads" kernel command line parameter that can be set in order to do so. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Rusty Russell Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12340/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-cps.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 06512171fd19..1061bd2e7e9c 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -27,14 +27,25 @@ #include #include +static bool threads_disabled; static DECLARE_BITMAP(core_power, NR_CPUS); struct core_boot_config *mips_cps_core_bootcfg; +static int __init setup_nothreads(char *s) +{ + threads_disabled = true; + return 0; +} +early_param("nothreads", setup_nothreads); + static unsigned core_vpe_count(unsigned core) { unsigned cfg; + if (threads_disabled) + return 1; + if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp)) return 1; -- cgit v1.2.3-59-g8ed1b From 6609ccdc852f7bfbfa54300dd5b3cd89eb4ced6f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:35 +0000 Subject: MIPS: smp-cps: Stop printing EJTAG exceptions to UART When CONFIG_MIPS_CPS_NS16550 is enabled, some register state is dumped to the UART when an exception is taken via the BEV on secondary cores. EJTAG exceptions are architecturally expected to be handled by the BEV even when Status.BEV is 0. This effectively means that if userland executes an sdbbp instruction on a secondary core then the kernel dumps register state to the UART even though the exception is perfectly normal & expected. Prevent this by simply not dumping information to the UART for EJTAG exceptions. Fixes: 609cf6f2291a ("MIPS: CPS: Early debug using an ns16550-compatible UART") Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12341/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index c28138d53d32..51b98dc371b3 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -223,7 +223,6 @@ LEAF(excep_intex) .org 0x480 LEAF(excep_ejtag) - DUMP_EXCEP("EJTAG") PTR_LA k0, ejtag_debug_handler jr k0 nop -- cgit v1.2.3-59-g8ed1b From d4594b2763f2cb5bc13ca05e312a389d15462cdf Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 12:06:35 +0000 Subject: MIPS: SEAD3 can support MIPS32r6 CPUs There are CPUs/bitfiles available for use with SEAD3 boards which implement release 6 of the MIPS architecture. Allow building the kernel for such a system. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12372/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e77a439c1932..b5609111a3bd 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -509,6 +509,7 @@ config MIPS_SEAD3 select MIPS_MSC select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS32_R6 select SYS_HAS_CPU_MIPS64_R1 select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL -- cgit v1.2.3-59-g8ed1b From bff3d472b82300274cac16007d76a70d67c7a643 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Mar 2016 00:41:58 +0100 Subject: MIPS: : Reformat to 80 columns. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 631aa10fdebe..59b46feb37b1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -309,8 +309,8 @@ enum cpu_type_enum { CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, - CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150, - CPU_I6400, + CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, + CPU_M5150, CPU_I6400, /* * MIPS64 class processors -- cgit v1.2.3-59-g8ed1b From 5cd0d5beef2bf34e3ec850aa75637e73fd8f5f82 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:26:37 +0000 Subject: MIPS: Add P6600 PRID & cpu_type_enum values Define the processor ID for the P6600 core and add a value to the enum cpu_type_enum for the core. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12342/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 59b46feb37b1..7773b8e0de1e 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -118,6 +118,7 @@ #define PRID_IMP_INTERAPTIV_MP 0xa100 #define PRID_IMP_PROAPTIV_UP 0xa200 #define PRID_IMP_PROAPTIV_MP 0xa300 +#define PRID_IMP_P6600 0xa400 #define PRID_IMP_M5150 0xa700 #define PRID_IMP_P5600 0xa800 #define PRID_IMP_I6400 0xa900 @@ -310,7 +311,7 @@ enum cpu_type_enum { CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, - CPU_M5150, CPU_I6400, + CPU_M5150, CPU_I6400, CPU_P6600, /* * MIPS64 class processors -- cgit v1.2.3-59-g8ed1b From 1091bfa20b94ba14a3c8a3eaf3a5b9d3df975da2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:26:38 +0000 Subject: MIPS: Add P6600 cases to CPU switch statements Add cases supporting the P6600 CPU to various switch statements in core MIPS kernel code that define behaviour dependent upon the CPU. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Peter Zijlstra Cc: Joshua Kinard Cc: Andrzej Hajda Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: James Hogan Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Petri Gynther Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12343/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-type.h | 1 + arch/mips/kernel/cpu-probe.c | 1 + arch/mips/kernel/perf_event_mipsxx.c | 6 ++++++ arch/mips/kernel/spram.c | 1 + arch/mips/kernel/traps.c | 1 + arch/mips/mm/c-r4k.c | 1 + arch/mips/mm/sc-mips.c | 1 + 7 files changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index abee2bfd10dc..2cb0979b5dc5 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -79,6 +79,7 @@ static inline int __pure __get_cpu_type(const int cpu_type) #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6 case CPU_I6400: + case CPU_P6600: #endif #ifdef CONFIG_SYS_HAS_CPU_R3000 diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e0cfa3b85bca..388503867657 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -539,6 +539,7 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) switch (c->cputype) { case CPU_PROAPTIV: case CPU_P5600: + case CPU_P6600: /* proAptiv & related cores use Config6 to enable the FTLB */ config = read_c0_config6(); /* Clear the old probability value */ diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 9bc1191b1ab0..656769c166fc 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) #endif break; case CPU_P5600: + case CPU_P6600: case CPU_I6400: /* 8-bit event numbers */ raw_id = config & 0x1ff; @@ -1718,6 +1719,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map2; mipspmu.cache_event_map = &mipsxxcore_cache_map2; break; + case CPU_P6600: + mipspmu.name = "mips/P6600"; + mipspmu.general_event_map = &mipsxxcore_event_map2; + mipspmu.cache_event_map = &mipsxxcore_cache_map2; + break; case CPU_I6400: mipspmu.name = "mips/I6400"; mipspmu.general_event_map = &mipsxxcore_event_map2; diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c index 8489c88f9932..d6e6cf75114d 100644 --- a/arch/mips/kernel/spram.c +++ b/arch/mips/kernel/spram.c @@ -210,6 +210,7 @@ void spram_config(void) case CPU_P5600: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: config0 = read_c0_config(); /* FIXME: addresses are Malta specific */ if (config0 & (1<<24)) { diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index bd4893feffa6..4358f025b752 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1644,6 +1644,7 @@ static inline void parity_protection_init(void) case CPU_P5600: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: { #define ERRCTL_PE 0x80000000 #define ERRCTL_L2P 0x00800000 diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 69e7e5873af3..729a7d48ceee 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1285,6 +1285,7 @@ static void probe_pcache(void) case CPU_M5150: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: if (!(read_c0_config7() & MIPS_CONF7_IAR) && (c->icache.waysize > PAGE_SIZE)) c->icache.flags |= MIPS_CACHE_ALIASES; diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 91dec32c77b7..286a4d5a1884 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -141,6 +141,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) case CPU_P5600: case CPU_BMIPS5000: case CPU_QEMU_GENERIC: + case CPU_P6600: if (config2 & (1 << 12)) return 0; } -- cgit v1.2.3-59-g8ed1b From eba20a3a37ff9fe8a4ae99f108ee4ce52db61247 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:26:39 +0000 Subject: MIPS: Probe the P6600 core Support probing the P6600 core now that cases for handling it have been added throughout the core MIPS kernel code. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12344/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 388503867657..0aa5bb06bb47 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1317,6 +1317,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_P5600; __cpu_name[cpu] = "MIPS P5600"; break; + case PRID_IMP_P6600: + c->cputype = CPU_P6600; + __cpu_name[cpu] = "MIPS P6600"; + break; case PRID_IMP_I6400: c->cputype = CPU_I6400; __cpu_name[cpu] = "MIPS I6400"; -- cgit v1.2.3-59-g8ed1b From df8b1a5ee9f7f5fbb5e8f0df9537c648481019ea Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 16:17:28 +0000 Subject: MIPS: Add M6250 PRID & cpu_type_enum values Define the processor ID for the M6250 CPU and add a value to the enum cpu_type_enum for the core. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12373/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 7773b8e0de1e..a7a91857950c 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -122,6 +122,7 @@ #define PRID_IMP_M5150 0xa700 #define PRID_IMP_P5600 0xa800 #define PRID_IMP_I6400 0xa900 +#define PRID_IMP_M6250 0xab00 /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -311,7 +312,7 @@ enum cpu_type_enum { CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, - CPU_M5150, CPU_I6400, CPU_P6600, + CPU_M5150, CPU_I6400, CPU_P6600, CPU_M6250, /* * MIPS64 class processors -- cgit v1.2.3-59-g8ed1b From 1dbf6a81c845a748e46b4bcaf25d958038624ad8 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 16:17:29 +0000 Subject: MIPS: Add M6250 cases to CPU switch statements Add casses supporting the M6250 CPU to various switch statements in the core MIPS kernel code that define behaviour dependent upon the CPU. Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12374/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-type.h | 4 ++++ arch/mips/mm/c-r4k.c | 1 + 2 files changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 2cb0979b5dc5..fbe1881f28fc 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type) */ #endif +#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R6 + case CPU_M6250: +#endif + #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6 case CPU_I6400: case CPU_P6600: diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 729a7d48ceee..e64d595fdcf2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1286,6 +1286,7 @@ static void probe_pcache(void) case CPU_QEMU_GENERIC: case CPU_I6400: case CPU_P6600: + case CPU_M6250: if (!(read_c0_config7() & MIPS_CONF7_IAR) && (c->icache.waysize > PAGE_SIZE)) c->icache.flags |= MIPS_CACHE_ALIASES; -- cgit v1.2.3-59-g8ed1b From 43aff742b64d8756d5612f4805af89635ae6c622 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 16:17:30 +0000 Subject: MIPS: Probe the M6250 CPU Support probing the M6250 CPU now that cases for handling it have been added where required in the core MIPS kernel code. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Joshua Kinard Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12375/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 0aa5bb06bb47..785e9a11c721 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1329,6 +1329,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_M5150; __cpu_name[cpu] = "MIPS M5150"; break; + case PRID_IMP_M6250: + c->cputype = CPU_M6250; + __cpu_name[cpu] = "MIPS M6250"; + break; } decode_configs(c); -- cgit v1.2.3-59-g8ed1b From 55d791f37c905b9ca68b96cdab89678654a5d16e Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 4 Feb 2016 13:05:03 +0000 Subject: MIPS: module: Make consistent use of pr_*() The module relocation handling code has inconsistent use of printk() and pr_*() functions. Convert printk() calls to use pr_err() and pr_warn(). [paul.burton@imgtec.com: Do the same thing in module.c] Signed-off-by: Steven J. Hill Signed-off-by: James Hogan Signed-off-by: Paul Burton Cc: Andrey Konovalov Cc: Andrey Ryabinin Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12433/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/module-rela.c | 8 +++----- arch/mips/kernel/module.c | 7 +++---- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c index 9083d63b765c..0570676b10e2 100644 --- a/arch/mips/kernel/module-rela.c +++ b/arch/mips/kernel/module-rela.c @@ -35,15 +35,13 @@ static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) { if (v % 4) { - pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", + pr_err("module %s: dangerous R_MIPS_26 RELA relocation\n", me->name); return -ENOEXEC; } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { - printk(KERN_ERR - "module %s: relocation overflow\n", - me->name); + pr_err("module %s: relocation overflow\n", me->name); return -ENOEXEC; } @@ -130,7 +128,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, /* Ignore unresolved weak symbol */ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) continue; - printk(KERN_WARNING "%s: Unknown symbol %s\n", + pr_warn("%s: Unknown symbol %s\n", me->name, strtab + sym->st_name); return -ENOENT; } diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index f9b2936d598d..e16624f57fd5 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -73,8 +73,7 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { - printk(KERN_ERR - "module %s: relocation overflow\n", + pr_err("module %s: relocation overflow\n", me->name); return -ENOEXEC; } @@ -219,8 +218,8 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, /* Ignore unresolved weak symbol */ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) continue; - printk(KERN_WARNING "%s: Unknown symbol %s\n", - me->name, strtab + sym->st_name); + pr_warn("%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); return -ENOENT; } -- cgit v1.2.3-59-g8ed1b From ad8319ea4647c897c837643a611714a83d8f6a0f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 4 Feb 2016 13:05:04 +0000 Subject: MIPS: Support R_MIPS_PC{21,26} rela-style relocs MIPS64 code uses rela-style relocs, and MIPS64r6 modules may include the new R_MIPS_PC21 & R_MIPS_PC26 relocations. We thus need to support these relocations in order to load MIPS64r6 kernel modules. They are similar to the existing R_MIPS_PC16 relocation but applying to a wider field. Implement support for them by genericising the existing R_MIPS_PC16 implementation such that it can be used for different field widths, and calling it for all 3 reloc types. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Kees Cook Cc: James Hogan Cc: Alex Smith Cc: Steven J. Hill Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12434/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 5 +++++ arch/mips/kernel/module-rela.c | 48 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index e090fc388e02..1bcbadb445fb 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -110,6 +110,11 @@ */ #define R_MIPS_CALLHI16 30 #define R_MIPS_CALLLO16 31 +/* + * Introduced for MIPSr6. + */ +#define R_MIPS_PC21_S2 60 +#define R_MIPS_PC26_S2 61 /* * This range is reserved for vendor specific relocations. */ diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c index 0570676b10e2..b3611426b128 100644 --- a/arch/mips/kernel/module-rela.c +++ b/arch/mips/kernel/module-rela.c @@ -16,6 +16,7 @@ * Copyright (C) 2001 Rusty Russell. * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2005 Thiemo Seufer + * Copyright (C) 2015 Imagination Technologies Ltd. */ #include @@ -65,6 +66,48 @@ static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) return 0; } +static int apply_r_mips_pc_rela(struct module *me, u32 *location, Elf_Addr v, + unsigned bits) +{ + unsigned long mask = GENMASK(bits - 1, 0); + unsigned long se_bits; + long offset; + + if (v % 4) { + pr_err("module %s: dangerous R_MIPS_PC%u RELA relocation\n", + me->name, bits); + return -ENOEXEC; + } + + offset = ((long)v - (long)location) >> 2; + + /* check the sign bit onwards are identical - ie. we didn't overflow */ + se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0; + if ((offset & ~mask) != (se_bits & ~mask)) { + pr_err("module %s: relocation overflow\n", me->name); + return -ENOEXEC; + } + + *location = (*location & ~mask) | (offset & mask); + + return 0; +} + +static int apply_r_mips_pc16_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 16); +} + +static int apply_r_mips_pc21_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 21); +} + +static int apply_r_mips_pc26_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 26); +} + static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) { *(Elf_Addr *)location = v; @@ -97,9 +140,12 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, [R_MIPS_26] = apply_r_mips_26_rela, [R_MIPS_HI16] = apply_r_mips_hi16_rela, [R_MIPS_LO16] = apply_r_mips_lo16_rela, + [R_MIPS_PC16] = apply_r_mips_pc16_rela, [R_MIPS_64] = apply_r_mips_64_rela, [R_MIPS_HIGHER] = apply_r_mips_higher_rela, - [R_MIPS_HIGHEST] = apply_r_mips_highest_rela + [R_MIPS_HIGHEST] = apply_r_mips_highest_rela, + [R_MIPS_PC21_S2] = apply_r_mips_pc21_rela, + [R_MIPS_PC26_S2] = apply_r_mips_pc26_rela, }; int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, -- cgit v1.2.3-59-g8ed1b From 5d3c792583b6040607e178925ccc8316a207210f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 4 Feb 2016 13:05:05 +0000 Subject: MIPS: Support R_MIPS_PC{16,21,26} rel-style relocs MIPS32 code uses rel-style relocs, and MIPS32r6 modules may include R_MIPS_PC16, R_MIPS_PC21 & R_MIPS_PC26 relocations. We thus need to support these relocations in order to load MIPS32r6 kernel modules. This patch adds such support, which is similar to the rela-style support in module-rela.c but making use of the implicit addend from the instruction encoding. Signed-off-by: Paul Burton Cc: Steven J. Hill Cc: Andrey Ryabinin Cc: James Hogan Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12435/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/module.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index e16624f57fd5..ff5d97d2e670 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -182,13 +182,62 @@ out_danger: return -ENOEXEC; } +static int apply_r_mips_pc_rel(struct module *me, u32 *location, Elf_Addr v, + unsigned bits) +{ + unsigned long mask = GENMASK(bits - 1, 0); + unsigned long se_bits; + long offset; + + if (v % 4) { + pr_err("module %s: dangerous R_MIPS_PC%u REL relocation\n", + me->name, bits); + return -ENOEXEC; + } + + /* retrieve & sign extend implicit addend */ + offset = *location & mask; + offset |= (offset & BIT(bits - 1)) ? ~mask : 0; + + offset += ((long)v - (long)location) >> 2; + + /* check the sign bit onwards are identical - ie. we didn't overflow */ + se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0; + if ((offset & ~mask) != (se_bits & ~mask)) { + pr_err("module %s: relocation overflow\n", me->name); + return -ENOEXEC; + } + + *location = (*location & ~mask) | (offset & mask); + + return 0; +} + +static int apply_r_mips_pc16_rel(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rel(me, location, v, 16); +} + +static int apply_r_mips_pc21_rel(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rel(me, location, v, 21); +} + +static int apply_r_mips_pc26_rel(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rel(me, location, v, 26); +} + static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, Elf_Addr v) = { [R_MIPS_NONE] = apply_r_mips_none, [R_MIPS_32] = apply_r_mips_32_rel, [R_MIPS_26] = apply_r_mips_26_rel, [R_MIPS_HI16] = apply_r_mips_hi16_rel, - [R_MIPS_LO16] = apply_r_mips_lo16_rel + [R_MIPS_LO16] = apply_r_mips_lo16_rel, + [R_MIPS_PC16] = apply_r_mips_pc16_rel, + [R_MIPS_PC21_S2] = apply_r_mips_pc21_rel, + [R_MIPS_PC26_S2] = apply_r_mips_pc26_rel, }; int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, -- cgit v1.2.3-59-g8ed1b From 04cc89d120f94131de89a6e20da27016db4782ce Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 27 Mar 2016 00:07:14 +0100 Subject: MIPS: Make flush_thread Avoids function calls to an empty function. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/processor.h | 4 ++++ arch/mips/kernel/process.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 041153f5cf93..cfa15bad43af 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -355,6 +355,10 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); */ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); +static inline void flush_thread(void) +{ +} + unsigned long get_wchan(struct task_struct *p); #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 3f5aa3bc191e..f57891616357 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -77,10 +77,6 @@ void exit_thread(void) { } -void flush_thread(void) -{ -} - int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { /* -- cgit v1.2.3-59-g8ed1b From 885872b722b73b2026a48bdff4621f289be2b044 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Wed, 3 Feb 2016 18:01:36 +0000 Subject: MIPS: Octeon: Add Octeon III CN7xxx interface detection Add basic CN7XXX interface detection. This allows the kernel to boot with ethernet working as it initializes the ethernet ports with SGMII instead of defaulting to RGMII routines. Tested on the utm8 from Rhino Labs with a CN7130. Signed-off-by: Zubair Lutfullah Kakakhel Acked-by: David Daney Cc: janne.huttunen@nokia.com Cc: aaro.koskinen@nokia.com Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12376/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/cvmx-helper.c | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index 376701f41cc2..ff26d0217b87 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -87,6 +87,8 @@ int cvmx_helper_get_number_of_interfaces(void) return 9; if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) return 4; + if (OCTEON_IS_MODEL(OCTEON_CN7XXX)) + return 5; else return 3; } @@ -259,6 +261,41 @@ static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface) } } +/** + * @INTERNAL + * Return interface mode for CN7XXX. + */ +static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface) +{ + union cvmx_gmxx_inf_mode mode; + + mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); + + switch (interface) { + case 0: + case 1: + switch (mode.cn68xx.mode) { + case 0: + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + case 1: + case 2: + return CVMX_HELPER_INTERFACE_MODE_SGMII; + case 3: + return CVMX_HELPER_INTERFACE_MODE_XAUI; + default: + return CVMX_HELPER_INTERFACE_MODE_SGMII; + } + case 2: + return CVMX_HELPER_INTERFACE_MODE_NPI; + case 3: + return CVMX_HELPER_INTERFACE_MODE_LOOP; + case 4: + return CVMX_HELPER_INTERFACE_MODE_RGMII; + default: + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } +} + /** * Get the operating mode of an interface. Depending on the Octeon * chip and configuration, this function returns an enumeration @@ -277,6 +314,12 @@ cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) interface >= cvmx_helper_get_number_of_interfaces()) return CVMX_HELPER_INTERFACE_MODE_DISABLED; + /* + * OCTEON III models + */ + if (OCTEON_IS_MODEL(OCTEON_CN7XXX)) + return __cvmx_get_mode_cn7xxx(interface); + /* * Octeon II models */ -- cgit v1.2.3-59-g8ed1b From 036aff91c30a6f15d5bf25f22827abc26b6d06c1 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 30 Jan 2016 09:09:43 +0000 Subject: MIPS: math-emu: dsemul: Remove an unused bit in ADDIUPC emulation Avoid a reader's confusion, as the calculation is correct either way. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12283/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/dsemul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 46b964d2b79c..d4ceacd4fa12 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -60,7 +60,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) unsigned int rs; s32 v; - rs = (((insn.mm_a_format.rs + 0x1e) & 0xf) + 2); + rs = (((insn.mm_a_format.rs + 0xe) & 0xf) + 2); v = regs->cp0_epc & ~3; v += insn.mm_a_format.simmediate << 2; regs->regs[rs] = (long)v; -- cgit v1.2.3-59-g8ed1b From 738a3f79027bef44b0bd3bfcc325f53b518749d4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:50 -0800 Subject: MIPS: BMIPS: Add early CPU initialization code Port the stblinux-3.3 code to perform a bunch of CPU-specific initialization, make it compatible with run-time detection of the CPU, and unroll the brcmstb-specific macros: BDEV_RB(), BDEV_UNSET. The "pref 30" disabling is done as a quirk. This is a preliminary change to allow the use of the "rotr" instruction gated by cpu_has_rixi. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12504/ Signed-off-by: Ralf Baechle --- arch/mips/bmips/setup.c | 1 + arch/mips/include/asm/bmips.h | 1 + arch/mips/kernel/smp-bmips.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) (limited to 'arch') diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index 35535284b39e..b764995343c1 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -111,6 +111,7 @@ static const struct bmips_quirk bmips_quirk_list[] = { void __init prom_init(void) { + bmips_cpu_setup(); register_bmips_smp_ops(); } diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index 6d25ad33ec78..a92aee7b977a 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -88,6 +88,7 @@ extern unsigned long bmips_tp1_irqs; extern void bmips_ebase_setup(void); extern asmlinkage void plat_wired_tlb_setup(void); +extern void bmips_cpu_setup(void); static inline unsigned long bmips_read_zscm_reg(unsigned int offset) { diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 6d11788b4502..e02addc0307f 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -566,3 +566,90 @@ asmlinkage void __weak plat_wired_tlb_setup(void) * once the wired entries are present. */ } + +void __init bmips_cpu_setup(void) +{ + void __iomem __maybe_unused *cbr = BMIPS_GET_CBR(); + u32 __maybe_unused cfg; + + switch (current_cpu_type()) { + case CPU_BMIPS3300: + /* Set BIU to async mode */ + set_c0_brcm_bus_pll(BIT(22)); + __sync(); + + /* put the BIU back in sync mode */ + clear_c0_brcm_bus_pll(BIT(22)); + + /* clear BHTD to enable branch history table */ + clear_c0_brcm_reset(BIT(16)); + + /* Flush and enable RAC */ + cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); + __raw_writel(cfg | 0x100, BMIPS_RAC_CONFIG); + __raw_readl(cbr + BMIPS_RAC_CONFIG); + + cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); + __raw_writel(cfg | 0xf, BMIPS_RAC_CONFIG); + __raw_readl(cbr + BMIPS_RAC_CONFIG); + + cfg = __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); + __raw_writel(cfg | 0x0fff0000, cbr + BMIPS_RAC_ADDRESS_RANGE); + __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); + break; + + case CPU_BMIPS4380: + /* CBG workaround for early BMIPS4380 CPUs */ + switch (read_c0_prid()) { + case 0x2a040: + case 0x2a042: + case 0x2a044: + case 0x2a060: + cfg = __raw_readl(cbr + BMIPS_L2_CONFIG); + __raw_writel(cfg & ~0x07000000, cbr + BMIPS_L2_CONFIG); + __raw_readl(cbr + BMIPS_L2_CONFIG); + } + + /* clear BHTD to enable branch history table */ + clear_c0_brcm_config_0(BIT(21)); + + /* XI/ROTR enable */ + set_c0_brcm_config_0(BIT(23)); + set_c0_brcm_cmt_ctrl(BIT(15)); + break; + + case CPU_BMIPS5000: + /* enable RDHWR, BRDHWR */ + set_c0_brcm_config(BIT(17) | BIT(21)); + + /* Disable JTB */ + __asm__ __volatile__( + " .set noreorder\n" + " li $8, 0x5a455048\n" + " .word 0x4088b00f\n" /* mtc0 t0, $22, 15 */ + " .word 0x4008b008\n" /* mfc0 t0, $22, 8 */ + " li $9, 0x00008000\n" + " or $8, $8, $9\n" + " .word 0x4088b008\n" /* mtc0 t0, $22, 8 */ + " sync\n" + " li $8, 0x0\n" + " .word 0x4088b00f\n" /* mtc0 t0, $22, 15 */ + " .set reorder\n" + : : : "$8", "$9"); + + /* XI enable */ + set_c0_brcm_config(BIT(27)); + + /* enable MIPS32R2 ROR instruction for XI TLB handlers */ + __asm__ __volatile__( + " li $8, 0x5a455048\n" + " .word 0x4088b00f\n" /* mtc0 $8, $22, 15 */ + " nop; nop; nop\n" + " .word 0x4008b008\n" /* mfc0 $8, $22, 8 */ + " lui $9, 0x0100\n" + " or $8, $9\n" + " .word 0x4088b008\n" /* mtc0 $8, $22, 8 */ + : : : "$8", "$9"); + break; + } +} -- cgit v1.2.3-59-g8ed1b From c0291f7c735941f2cf5c8d5264c2cc2402b77869 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 13 May 2015 16:17:13 +0100 Subject: MIPS: cpu: Alter MIPS_CPU_* definitions to fill gap The MIPS_CPU_* definitions accidentally missed bits 27..30 when MIPS_CPU_EVA was added, and further definitions have continued from there. Shift all the definitions since MIPS_CPU_EVA right by 4 so there are no gaps. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10044/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a7a91857950c..a9a5aa75a863 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -379,14 +379,14 @@ enum cpu_type_enum { #define MIPS_CPU_MICROMIPS 0x01000000ull /* CPU has microMIPS capability */ #define MIPS_CPU_TLBINV 0x02000000ull /* CPU supports TLBINV/F */ #define MIPS_CPU_SEGMENTS 0x04000000ull /* CPU supports Segmentation Control registers */ -#define MIPS_CPU_EVA 0x80000000ull /* CPU supports Enhanced Virtual Addressing */ -#define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */ -#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ -#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ -#define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ -#define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */ -#define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ +#define MIPS_CPU_EVA 0x08000000ull /* CPU supports Enhanced Virtual Addressing */ +#define MIPS_CPU_HTW 0x10000000ull /* CPU support Hardware Page Table Walker */ +#define MIPS_CPU_RIXIEX 0x20000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ +#define MIPS_CPU_MAAR 0x40000000ull /* MAAR(I) registers are present */ +#define MIPS_CPU_FRE 0x80000000ull /* FRE & UFE bits implemented */ +#define MIPS_CPU_RW_LLB 0x100000000ull /* LLADDR/LLB writes are allowed */ +#define MIPS_CPU_XPA 0x200000000ull /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_CDMM 0x400000000ull /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ #define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ -- cgit v1.2.3-59-g8ed1b From 0c94fa33b4de55a0dcb60519ba04a0fd49da124d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 13 May 2015 16:17:14 +0100 Subject: MIPS: cpu: Convert MIPS_CPU_* defs to (1ull << x) The MIPS_CPU_* definitions have now filled the first 32-bits, and are getting longer since they're written in hex without zero padding. Adding my 8 extra MIPS_CPU_* definitions which I haven't upstreamed yet this is getting increasingly ugly as the comments get shifted progressively to the right. Its also error prone, and I've seen this cause mistakes on 3 separate occasions now, not helped by it being a conflict hotspot. Convert all the MIPS_CPU_* definitions to the form (1ull << x). Humans are better at incrementing than shifting. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10045/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 89 ++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 41 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a9a5aa75a863..cc579a6c8016 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -349,50 +349,57 @@ enum cpu_type_enum { MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \ MIPS_CPU_ISA_M64R6) +/* + * Private version of BIT_ULL() to escape include file recursion hell. + * We soon will have to switch to another mechanism that will work with + * more than 64 bits anyway. + */ +#define MBIT_ULL(bit) (1ULL << (bit)) + /* * CPU Option encodings */ -#define MIPS_CPU_TLB 0x00000001ull /* CPU has TLB */ -#define MIPS_CPU_4KEX 0x00000002ull /* "R4K" exception model */ -#define MIPS_CPU_3K_CACHE 0x00000004ull /* R3000-style caches */ -#define MIPS_CPU_4K_CACHE 0x00000008ull /* R4000-style caches */ -#define MIPS_CPU_TX39_CACHE 0x00000010ull /* TX3900-style caches */ -#define MIPS_CPU_FPU 0x00000020ull /* CPU has FPU */ -#define MIPS_CPU_32FPR 0x00000040ull /* 32 dbl. prec. FP registers */ -#define MIPS_CPU_COUNTER 0x00000080ull /* Cycle count/compare */ -#define MIPS_CPU_WATCH 0x00000100ull /* watchpoint registers */ -#define MIPS_CPU_DIVEC 0x00000200ull /* dedicated interrupt vector */ -#define MIPS_CPU_VCE 0x00000400ull /* virt. coherence conflict possible */ -#define MIPS_CPU_CACHE_CDEX_P 0x00000800ull /* Create_Dirty_Exclusive CACHE op */ -#define MIPS_CPU_CACHE_CDEX_S 0x00001000ull /* ... same for seconary cache ... */ -#define MIPS_CPU_MCHECK 0x00002000ull /* Machine check exception */ -#define MIPS_CPU_EJTAG 0x00004000ull /* EJTAG exception */ -#define MIPS_CPU_NOFPUEX 0x00008000ull /* no FPU exception */ -#define MIPS_CPU_LLSC 0x00010000ull /* CPU has ll/sc instructions */ -#define MIPS_CPU_INCLUSIVE_CACHES 0x00020000ull /* P-cache subset enforced */ -#define MIPS_CPU_PREFETCH 0x00040000ull /* CPU has usable prefetch */ -#define MIPS_CPU_VINT 0x00080000ull /* CPU supports MIPSR2 vectored interrupts */ -#define MIPS_CPU_VEIC 0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */ -#define MIPS_CPU_ULRI 0x00200000ull /* CPU has ULRI feature */ -#define MIPS_CPU_PCI 0x00400000ull /* CPU has Perf Ctr Int indicator */ -#define MIPS_CPU_RIXI 0x00800000ull /* CPU has TLB Read/eXec Inhibit */ -#define MIPS_CPU_MICROMIPS 0x01000000ull /* CPU has microMIPS capability */ -#define MIPS_CPU_TLBINV 0x02000000ull /* CPU supports TLBINV/F */ -#define MIPS_CPU_SEGMENTS 0x04000000ull /* CPU supports Segmentation Control registers */ -#define MIPS_CPU_EVA 0x08000000ull /* CPU supports Enhanced Virtual Addressing */ -#define MIPS_CPU_HTW 0x10000000ull /* CPU support Hardware Page Table Walker */ -#define MIPS_CPU_RIXIEX 0x20000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ -#define MIPS_CPU_MAAR 0x40000000ull /* MAAR(I) registers are present */ -#define MIPS_CPU_FRE 0x80000000ull /* FRE & UFE bits implemented */ -#define MIPS_CPU_RW_LLB 0x100000000ull /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA 0x200000000ull /* CPU supports Extended Physical Addressing */ -#define MIPS_CPU_CDMM 0x400000000ull /* CPU has Common Device Memory Map */ -#define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ -#define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ -#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ -#define MIPS_CPU_NAN_LEGACY 0x40000000000ull /* Legacy NaN implemented */ -#define MIPS_CPU_NAN_2008 0x80000000000ull /* 2008 NaN implemented */ -#define MIPS_CPU_VP 0x100000000000ull /* MIPSr6 Virtual Processors (multi-threading) */ +#define MIPS_CPU_TLB MBIT_ULL( 0) /* CPU has TLB */ +#define MIPS_CPU_4KEX MBIT_ULL( 1) /* "R4K" exception model */ +#define MIPS_CPU_3K_CACHE MBIT_ULL( 2) /* R3000-style caches */ +#define MIPS_CPU_4K_CACHE MBIT_ULL( 3) /* R4000-style caches */ +#define MIPS_CPU_TX39_CACHE MBIT_ULL( 4) /* TX3900-style caches */ +#define MIPS_CPU_FPU MBIT_ULL( 5) /* CPU has FPU */ +#define MIPS_CPU_32FPR MBIT_ULL( 6) /* 32 dbl. prec. FP registers */ +#define MIPS_CPU_COUNTER MBIT_ULL( 7) /* Cycle count/compare */ +#define MIPS_CPU_WATCH MBIT_ULL( 8) /* watchpoint registers */ +#define MIPS_CPU_DIVEC MBIT_ULL( 9) /* dedicated interrupt vector */ +#define MIPS_CPU_VCE MBIT_ULL(10) /* virt. coherence conflict possible */ +#define MIPS_CPU_CACHE_CDEX_P MBIT_ULL(11) /* Create_Dirty_Exclusive CACHE op */ +#define MIPS_CPU_CACHE_CDEX_S MBIT_ULL(12) /* ... same for seconary cache ... */ +#define MIPS_CPU_MCHECK MBIT_ULL(13) /* Machine check exception */ +#define MIPS_CPU_EJTAG MBIT_ULL(14) /* EJTAG exception */ +#define MIPS_CPU_NOFPUEX MBIT_ULL(15) /* no FPU exception */ +#define MIPS_CPU_LLSC MBIT_ULL(16) /* CPU has ll/sc instructions */ +#define MIPS_CPU_INCLUSIVE_CACHES MBIT_ULL(17) /* P-cache subset enforced */ +#define MIPS_CPU_PREFETCH MBIT_ULL(18) /* CPU has usable prefetch */ +#define MIPS_CPU_VINT MBIT_ULL(19) /* CPU supports MIPSR2 vectored interrupts */ +#define MIPS_CPU_VEIC MBIT_ULL(20) /* CPU supports MIPSR2 external interrupt controller mode */ +#define MIPS_CPU_ULRI MBIT_ULL(21) /* CPU has ULRI feature */ +#define MIPS_CPU_PCI MBIT_ULL(22) /* CPU has Perf Ctr Int indicator */ +#define MIPS_CPU_RIXI MBIT_ULL(23) /* CPU has TLB Read/eXec Inhibit */ +#define MIPS_CPU_MICROMIPS MBIT_ULL(24) /* CPU has microMIPS capability */ +#define MIPS_CPU_TLBINV MBIT_ULL(25) /* CPU supports TLBINV/F */ +#define MIPS_CPU_SEGMENTS MBIT_ULL(26) /* CPU supports Segmentation Control registers */ +#define MIPS_CPU_EVA MBIT_ULL(27) /* CPU supports Enhanced Virtual Addressing */ +#define MIPS_CPU_HTW MBIT_ULL(28) /* CPU support Hardware Page Table Walker */ +#define MIPS_CPU_RIXIEX MBIT_ULL(29) /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ +#define MIPS_CPU_MAAR MBIT_ULL(30) /* MAAR(I) registers are present */ +#define MIPS_CPU_FRE MBIT_ULL(31) /* FRE & UFE bits implemented */ +#define MIPS_CPU_RW_LLB MBIT_ULL(32) /* LLADDR/LLB writes are allowed */ +#define MIPS_CPU_XPA MBIT_ULL(33) /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_CDMM MBIT_ULL(34) /* CPU has Common Device Memory Map */ +#define MIPS_CPU_BP_GHIST MBIT_ULL(35) /* R12K+ Branch Prediction Global History */ +#define MIPS_CPU_SP MBIT_ULL(36) /* Small (1KB) page support */ +#define MIPS_CPU_FTLB MBIT_ULL(37) /* CPU has Fixed-page-size TLB */ +#define MIPS_CPU_NAN_LEGACY MBIT_ULL(38) /* Legacy NaN implemented */ +#define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ +#define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ /* * CPU ASE encodings -- cgit v1.2.3-59-g8ed1b From b5a6455cde3d63466ac31bacdb42afcf30932f75 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Tue, 29 Mar 2016 15:50:25 +0100 Subject: MIPS: Detect DSP v3 support DSPv3 is supported on all MIPSr6 systems which indicate support for DSPv2. This doesn't require any changes to the kernel's handling of DSP resources. The patch is to detect support and indicate it in /proc/cpuinfo DSP v3 introduces a new instruction BPOSGE32C Signed-off-by: Zubair Lutfullah Kakakhel Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12918/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/kernel/cpu-probe.c | 5 ++++- arch/mips/kernel/proc.c | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 57cdc5be9545..6ff0504d090d 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -307,6 +307,10 @@ #define cpu_has_dsp2 (cpu_data[0].ases & MIPS_ASE_DSP2P) #endif +#ifndef cpu_has_dsp3 +#define cpu_has_dsp3 (cpu_data[0].ases & MIPS_ASE_DSP3) +#endif + #ifndef cpu_has_mipsmt #define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index cc579a6c8016..9127a583d1f1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -413,5 +413,6 @@ enum cpu_type_enum { #define MIPS_ASE_DSP2P 0x00000040 /* Signal Processing ASE Rev 2 */ #define MIPS_ASE_VZ 0x00000080 /* Virtualization ASE */ #define MIPS_ASE_MSA 0x00000100 /* MIPS SIMD Architecture */ +#define MIPS_ASE_DSP3 0x00000200 /* Signal Processing ASE Rev 3*/ #endif /* _ASM_CPU_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 785e9a11c721..d0818aab00e2 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -680,8 +680,11 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_RIXI; if (config3 & MIPS_CONF3_DSP) c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_DSP2P) + if (config3 & MIPS_CONF3_DSP2P) { c->ases |= MIPS_ASE_DSP2P; + if (cpu_has_mips_r6) + c->ases |= MIPS_ASE_DSP3; + } if (config3 & MIPS_CONF3_VINT) c->options |= MIPS_CPU_VINT; if (config3 & MIPS_CONF3_VEIC) diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 298b2b773d12..97dc01b03631 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -114,6 +114,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_smartmips) seq_printf(m, "%s", " smartmips"); if (cpu_has_dsp) seq_printf(m, "%s", " dsp"); if (cpu_has_dsp2) seq_printf(m, "%s", " dsp2"); + if (cpu_has_dsp3) seq_printf(m, "%s", " dsp3"); if (cpu_has_mipsmt) seq_printf(m, "%s", " mt"); if (cpu_has_mmips) seq_printf(m, "%s", " micromips"); if (cpu_has_vz) seq_printf(m, "%s", " vz"); -- cgit v1.2.3-59-g8ed1b From b4f37b2f2f7ed83847c8010b2649ea03ff429f43 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 2 Mar 2016 22:47:19 +0200 Subject: MIPS: OCTEON: cavium_octeon_defconfig: enable all OCTEON SoC drivers Some drivers for SoC provided functionality are missing. Enable to those in defconfig to provide better build/testing coverage. Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12750/ Signed-off-by: Ralf Baechle --- arch/mips/configs/cavium_octeon_defconfig | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index e57058d4ec22..dcac308cec39 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig @@ -119,14 +119,16 @@ CONFIG_SPI=y CONFIG_SPI_OCTEON=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y -# CONFIG_USB_SUPPORT is not set -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PLATFORM=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_STAGING=y CONFIG_OCTEON_ETHERNET=y +CONFIG_OCTEON_USB=m # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y @@ -152,6 +154,9 @@ CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MD5_OCTEON=y +CONFIG_CRYPTO_SHA1_OCTEON=m +CONFIG_CRYPTO_SHA256_OCTEON=m +CONFIG_CRYPTO_SHA512_OCTEON=m CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -- cgit v1.2.3-59-g8ed1b From 763fee97e743acb4f6e683a00fd2e7f5ad2484fb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:56 +0000 Subject: MIPS: Flush dcache for flush_kernel_dcache_page The flush_kernel_dcache_page function was previously essentially a nop. This is incorrect for MIPS, where if a page has been modified & either it aliases or it's executable & the icache doesn't fill from dcache then the content needs to be written back from dcache to the next level of the cache hierarchy (which is shared with the icache). Implement this by simply calling flush_dcache_page, treating this kmapped cache flush function (flush_kernel_dcache_page) exactly the same as its non-kmapped counterpart (flush_dcache_page). Signed-off-by: Paul Burton Cc: Lars Persson Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12719/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cacheflush.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 723229f4cf27..7e9f46818eba 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -132,6 +132,7 @@ static inline void kunmap_noncoherent(void) static inline void flush_kernel_dcache_page(struct page *page) { BUG_ON(cpu_has_dc_aliases && PageHighMem(page)); + flush_dcache_page(page); } /* -- cgit v1.2.3-59-g8ed1b From 234859e49a15323cf1b2331bdde7f658c4cb45fb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:57 +0000 Subject: MIPS: Flush highmem pages in __flush_dcache_page When flush_dcache_page is called on an executable page, that page is about to be provided to userland & we can presume that the icache contains no valid entries for its address range. However if the icache does not fill from the dcache then we cannot presume that the pages content has been written back as far as the memories that the dcache will fill from (ie. L2 or further out). This was being done for lowmem pages, but not for highmem which can lead to icache corruption. Fix this by mapping highmem pages & flushing their content from the dcache in __flush_dcache_page before providing the page to userland, just as is done for lowmem pages. Signed-off-by: Paul Burton Cc: Lars Persson Cc: Andrew Morton Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12720/ Signed-off-by: Ralf Baechle --- arch/mips/mm/cache.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 3f159caf6dbc..5a67d8c3decb 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -83,8 +84,6 @@ void __flush_dcache_page(struct page *page) struct address_space *mapping = page_mapping(page); unsigned long addr; - if (PageHighMem(page)) - return; if (mapping && !mapping_mapped(mapping)) { SetPageDcacheDirty(page); return; @@ -95,8 +94,15 @@ void __flush_dcache_page(struct page *page) * case is for exec env/arg pages and those are %99 certainly going to * get faulted into the tlb (and thus flushed) anyways. */ - addr = (unsigned long) page_address(page); + if (PageHighMem(page)) + addr = (unsigned long)kmap_atomic(page); + else + addr = (unsigned long)page_address(page); + flush_data_cache_page(addr); + + if (PageHighMem(page)) + __kunmap_atomic((void *)addr); } EXPORT_SYMBOL(__flush_dcache_page); -- cgit v1.2.3-59-g8ed1b From f4281bba818105c7c91799abe40bc05c0dbdaa25 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:58 +0000 Subject: MIPS: Handle highmem pages in __update_cache The following patch will expose __update_cache to highmem pages. Handle them by mapping them in for the duration of the cache maintenance, just like in __flush_dcache_page. The code for that isn't shared because we need the page address in __update_cache so sharing became messy. Given that the entirity is an extra 5 lines, just duplicate it. Signed-off-by: Paul Burton Cc: Lars Persson Cc: Andrew Morton Cc: Jerome Marchand Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: stable # v4.1+ Patchwork: https://patchwork.linux-mips.org/patch/12721/ Signed-off-by: Ralf Baechle --- arch/mips/mm/cache.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 5a67d8c3decb..8befa55234df 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -149,9 +149,17 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address, return; page = pfn_to_page(pfn); if (page_mapping(page) && Page_dcache_dirty(page)) { - addr = (unsigned long) page_address(page); + if (PageHighMem(page)) + addr = (unsigned long)kmap_atomic(page); + else + addr = (unsigned long)page_address(page); + if (exec || pages_do_alias(addr, address & PAGE_MASK)) flush_data_cache_page(addr); + + if (PageHighMem(page)) + __kunmap_atomic((void *)addr); + ClearPageDcacheDirty(page); } } -- cgit v1.2.3-59-g8ed1b From 37d22a0d798b5c938b277d32cfd86dc231381342 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:59 +0000 Subject: MIPS: Sync icache & dcache in set_pte_at It's possible for pages to become visible prior to update_mmu_cache running if a thread within the same address space preempts the current thread or runs simultaneously on another CPU. That is, the following scenario is possible: CPU0 CPU1 write to page flush_dcache_page flush_icache_page set_pte_at map page update_mmu_cache If CPU1 maps the page in between CPU0's set_pte_at, which marks it valid & visible, and update_mmu_cache where the dcache flush occurs then CPU1s icache will fill from stale data (unless it fills from the dcache, in which case all is good, but most MIPS CPUs don't have this property). Commit 4d46a67a3eb8 ("MIPS: Fix race condition in lazy cache flushing.") attempted to fix that by performing the dcache flush in flush_icache_page such that it occurs before the set_pte_at call makes the page visible. However it has the problem that not all code that writes to pages exposed to userland call flush_icache_page. There are many callers of set_pte_at under mm/ and only 2 of them do call flush_icache_page. Thus the race window between a page becoming visible & being coherent between the icache & dcache remains open in some cases. To illustrate some of the cases, a WARN was added to __update_cache with this patch applied that triggered in cases where a page about to be flushed from the dcache was not the last page provided to flush_icache_page. That is, backtraces were obtained for cases in which the race window is left open without this patch. The 2 standout examples follow. When forking a process: [ 15.271842] [<80417630>] __update_cache+0xcc/0x188 [ 15.277274] [<80530394>] copy_page_range+0x56c/0x6ac [ 15.282861] [<8042936c>] copy_process.part.54+0xd40/0x17ac [ 15.289028] [<80429f80>] do_fork+0xe4/0x420 [ 15.293747] [<80413808>] handle_sys+0x128/0x14c When exec'ing an ELF binary: [ 14.445964] [<80417630>] __update_cache+0xcc/0x188 [ 14.451369] [<80538d88>] move_page_tables+0x414/0x498 [ 14.457075] [<8055d848>] setup_arg_pages+0x220/0x318 [ 14.462685] [<805b0f38>] load_elf_binary+0x530/0x12a0 [ 14.468374] [<8055ec3c>] search_binary_handler+0xbc/0x214 [ 14.474444] [<8055f6c0>] do_execveat_common+0x43c/0x67c [ 14.480324] [<8055f938>] do_execve+0x38/0x44 [ 14.485137] [<80413808>] handle_sys+0x128/0x14c These code paths write into a page, call flush_dcache_page then call set_pte_at without flush_icache_page inbetween. The end result is that the icache can become corrupted & userland processes may execute unexpected or invalid code, typically resulting in a reserved instruction exception, a trap or a segfault. Fix this race condition fully by performing any cache maintenance required to keep the icache & dcache in sync in set_pte_at, before the page is made valid. This has the added bonus of ensuring the cache maintenance always happens in one location, rather than being duplicated in flush_icache_page & update_mmu_cache. It also matches the way other architectures solve the same problem (see arm, ia64 & powerpc). Signed-off-by: Paul Burton Reported-by: Ionela Voinescu Cc: Lars Persson Fixes: 4d46a67a3eb8 ("MIPS: Fix race condition in lazy cache flushing.") Cc: Steven J. Hill Cc: David Daney Cc: Huacai Chen Cc: Aneesh Kumar K.V Cc: Andrew Morton Cc: Jerome Marchand Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: stable # v4.1+ Patchwork: https://patchwork.linux-mips.org/patch/12722/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cacheflush.h | 6 ------ arch/mips/include/asm/pgtable.h | 26 +++++++++++++++++++++----- arch/mips/mm/cache.c | 19 +++---------------- 3 files changed, 24 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 7e9f46818eba..34ed22ec6c33 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); extern void __flush_dcache_page(struct page *page); -extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page); #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 static inline void flush_dcache_page(struct page *page) @@ -77,11 +76,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma, static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page) { - if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) && - Page_dcache_dirty(page)) { - __flush_icache_page(vma, page); - ClearPageDcacheDirty(page); - } } extern void (*flush_icache_range)(unsigned long start, unsigned long end); diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 75c29cff0f99..45de57651619 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -127,10 +127,14 @@ do { \ } \ } while(0) +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval); + #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) #define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) +#define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) static inline void set_pte(pte_t *ptep, pte_t pte) { @@ -148,7 +152,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte) buddy->pte_high |= _PAGE_GLOBAL; } } -#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -166,6 +169,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt #define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) +#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC) /* * Certain architectures need to do special things when pte's @@ -230,7 +234,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) } #endif } -#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -246,6 +249,22 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt } #endif +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) +{ + extern void __update_cache(unsigned long address, pte_t pte); + + if (!pte_present(pteval)) + goto cache_sync_done; + + if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval))) + goto cache_sync_done; + + __update_cache(addr, pteval); +cache_sync_done: + set_pte(ptep, pteval); +} + /* * (pmds are folded into puds so this doesn't get actually called, * but the define is needed for a generic inline function.) @@ -442,15 +461,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) extern void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte); -extern void __update_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte); static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { pte_t pte = *ptep; __update_tlb(vma, address, pte); - __update_cache(vma, address, pte); } static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 8befa55234df..bf04c6c479a4 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -125,30 +125,17 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) EXPORT_SYMBOL(__flush_anon_page); -void __flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - unsigned long addr; - - if (PageHighMem(page)) - return; - - addr = (unsigned long) page_address(page); - flush_data_cache_page(addr); -} -EXPORT_SYMBOL_GPL(__flush_icache_page); - -void __update_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte) +void __update_cache(unsigned long address, pte_t pte) { struct page *page; unsigned long pfn, addr; - int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; + int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc; pfn = pte_pfn(pte); if (unlikely(!pfn_valid(pfn))) return; page = pfn_to_page(pfn); - if (page_mapping(page) && Page_dcache_dirty(page)) { + if (Page_dcache_dirty(page)) { if (PageHighMem(page)) addr = (unsigned long)kmap_atomic(page); else -- cgit v1.2.3-59-g8ed1b From 3d2ca73af4eb4a33ae021e37b5f395ac5631cb3f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 27 Jan 2016 14:23:36 -0800 Subject: MIPS: Use generic clkdev.h header The generic header file is equivalent to the MIPS one, so use the generic one instead. Signed-off-by: Stephen Boyd Cc: linux-kernel@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12261/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/Kbuild | 1 + arch/mips/include/asm/clkdev.h | 27 --------------------------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 arch/mips/include/asm/clkdev.h (limited to 'arch') diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index c7fe4d01e79c..9740066cc631 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -1,5 +1,6 @@ # MIPS headers generic-(CONFIG_GENERIC_CSUM) += checksum.h +generic-y += clkdev.h generic-y += cputime.h generic-y += current.h generic-y += dma-contiguous.h diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h deleted file mode 100644 index 1b3ad7b09dc1..000000000000 --- a/arch/mips/include/asm/clkdev.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * based on arch/arm/include/asm/clkdev.h - * - * Copyright (C) 2008 Russell King. - * - * 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. - * - * Helper for the clk API to assist looking up a struct clk. - */ -#ifndef __ASM_CLKDEV_H -#define __ASM_CLKDEV_H - -#include - -#ifndef CONFIG_COMMON_CLK -#define __clk_get(clk) ({ 1; }) -#define __clk_put(clk) do { } while (0) -#endif - -static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) -{ - return kzalloc(size, GFP_KERNEL); -} - -#endif -- cgit v1.2.3-59-g8ed1b From e2c93cf14b40e8b8e755bb163ced004edb4691e2 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 30 Mar 2016 13:42:45 +0200 Subject: MIPS: defconfigs: Remove CONFIG_IPV6_PRIVACY Option is long gone, see 5d9efa7ee99e ("ipv6: Remove privacy config option.") Signed-off-by: Borislav Petkov Cc: linux-mips@linux-mips.org Cc: LKML Patchwork: https://patchwork.linux-mips.org/patch/12919/ Signed-off-by: Ralf Baechle --- arch/mips/configs/bcm47xx_defconfig | 1 - arch/mips/configs/bigsur_defconfig | 1 - arch/mips/configs/decstation_defconfig | 1 - arch/mips/configs/ip22_defconfig | 1 - arch/mips/configs/ip27_defconfig | 1 - arch/mips/configs/jazz_defconfig | 1 - arch/mips/configs/lemote2f_defconfig | 1 - arch/mips/configs/mtx1_defconfig | 1 - arch/mips/configs/nlm_xlp_defconfig | 1 - arch/mips/configs/nlm_xlr_defconfig | 1 - arch/mips/configs/rm200_defconfig | 1 - 11 files changed, 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig index 0db4eb319e0a..fad8e964f14c 100644 --- a/arch/mips/configs/bcm47xx_defconfig +++ b/arch/mips/configs/bcm47xx_defconfig @@ -23,7 +23,6 @@ CONFIG_IP_MROUTE=y CONFIG_IP_MROUTE_MULTIPLE_TABLES=y CONFIG_SYN_COOKIES=y CONFIG_TCP_CONG_ADVANCED=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y CONFIG_IPV6_MROUTE=y diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index e070dac071c8..d20b09d77b53 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -62,7 +62,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m # CONFIG_INET_LRO is not set CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index ebc011c51e5a..2b6cb41d5715 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -30,7 +30,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_INET_XFRM_MODE_BEET=m CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_INET6_AH=m diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 6ba9ce9fcdd5..5d83ff755547 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -48,7 +48,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_INET_XFRM_MODE_BEET=m # CONFIG_INET_LRO is not set CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 77e9f505f5e4..2b74aee320a1 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -43,7 +43,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_INET_XFRM_MODE_BEET=m CONFIG_TCP_MD5SIG=y CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index a5e85e1ee5de..3019fce63cd3 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -34,7 +34,6 @@ CONFIG_IP_PIMSM_V2=y CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_INET6_AH=m diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig index d1f198b072a0..5da76e0e120f 100644 --- a/arch/mips/configs/lemote2f_defconfig +++ b/arch/mips/configs/lemote2f_defconfig @@ -71,7 +71,6 @@ CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_CONG_BIC=y CONFIG_DEFAULT_BIC=y CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index 9b6926d6bb32..f3f60056bc27 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -51,7 +51,6 @@ CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m diff --git a/arch/mips/configs/nlm_xlp_defconfig b/arch/mips/configs/nlm_xlp_defconfig index b3d1d37f85ea..b496c25fced6 100644 --- a/arch/mips/configs/nlm_xlp_defconfig +++ b/arch/mips/configs/nlm_xlp_defconfig @@ -95,7 +95,6 @@ CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m CONFIG_TCP_MD5SIG=y CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig index 3d8016d6cf3e..8e99ad807a57 100644 --- a/arch/mips/configs/nlm_xlr_defconfig +++ b/arch/mips/configs/nlm_xlr_defconfig @@ -75,7 +75,6 @@ CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m CONFIG_TCP_MD5SIG=y CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 82db4e3e4cf1..c2b4e3f33a73 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -37,7 +37,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m CONFIG_INET_XFRM_MODE_BEET=m CONFIG_TCP_MD5SIG=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_INET6_AH=m -- cgit v1.2.3-59-g8ed1b From 8571e645d1d15a560a32d262817f3b1d901cedac Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Thu, 26 Nov 2015 11:00:08 +0100 Subject: pinctrl/lantiq: update devicetree binding in dts file This patch updates the compatible string in the easy50712.dts file to the new "lantiq,danube-pinctrl". Signed-off-by: Martin Schiller Acked-by: Linus Walleij Cc: robh+dt@kernel.org Cc: pawel.moll@arm.com Cc: mark.rutland@arm.com Cc: ijc+devicetree@hellion.org.uk Cc: galak@codeaurora.org Cc: john@phrozen.org Cc: hauke@hauke-m.de Cc: jogo@openwrt.org Cc: daniel.schwierzeck@gmail.com Cc: linux-gpio@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11589/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/lantiq/easy50712.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/lantiq/easy50712.dts b/arch/mips/boot/dts/lantiq/easy50712.dts index 143b8a37b5e4..b59962585dde 100644 --- a/arch/mips/boot/dts/lantiq/easy50712.dts +++ b/arch/mips/boot/dts/lantiq/easy50712.dts @@ -52,7 +52,7 @@ }; gpio: pinmux@E100B10 { - compatible = "lantiq,pinctrl-xway"; + compatible = "lantiq,danube-pinctrl"; pinctrl-names = "default"; pinctrl-0 = <&state_default>; -- cgit v1.2.3-59-g8ed1b From 5050e91fa650ecd6260ef62bbed9dfc5b4d05dfa Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Tue, 29 Mar 2016 09:35:30 +0100 Subject: MIPS: Support sending SIG_SYS to 32bit userspace from 64bit kernel The seccomp_bpf self test revealed that a 64bit kernel delivered an invalid SIG_SYS to a 32bit userspace, because it was falling into the default of the switch statement. Add a case to handle delivering the signal. With this patch, the seccomp_bpf self test now passes the TRAP.handler case with O32 and N32 userlands. Signed-off-by: Matt Redfearn Acked-by: Kees Cook Cc: Paul Burton Cc: Amanieu d'Antras Cc: Alex Smith Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: IMG-MIPSLinuxKerneldevelopers@imgtec.com Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12915/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/signal32.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 4909639aa35b..78c8349d151c 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -227,6 +227,12 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); break; + case __SI_SYS >> 16: + err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr, + sizeof(compat_uptr_t)); + err |= __put_user(from->si_syscall, &to->si_syscall); + err |= __put_user(from->si_arch, &to->si_arch); + break; } } return err; -- cgit v1.2.3-59-g8ed1b From a400bed6d105c23d3673f763596e4b85de14e41a Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Tue, 29 Mar 2016 09:35:31 +0100 Subject: MIPS: scall: Handle seccomp filters which redirect syscalls Commit d218af78492a ("MIPS: scall: Always run the seccomp syscall filters") modified the syscall code to always call the seccomp filters, but missed the case where a filter may redirect the syscall, as revealed by the seccomp_bpf self test. The syscall path now restores the syscall from the stack after the filter rather than saving it locally. Syscall number checking and syscall function table lookup is done after the filter may have run such that redirected syscalls are also checked, and executed. The regular path of syscall number checking and pointer lookup is also made more consistent between ABIs with scall64-64.S being the reference. With this patch in place, the seccomp_bpf self test now passes TRACE_syscall.syscall_redirected and TRACE_syscall.syscall_dropped on all MIPS ABIs. Fixes: d218af78492a ("MIPS: scall: Always run the seccomp syscall filters") Signed-off-by: Matt Redfearn Acked-by: Kees Cook Cc: Eric B Munson Cc: James Hogan Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: IMG-MIPSLinuxKerneldevelopers@imgtec.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12916/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/scall32-o32.S | 11 +++++------ arch/mips/kernel/scall64-64.S | 3 +-- arch/mips/kernel/scall64-n32.S | 14 +++++++++----- arch/mips/kernel/scall64-o32.S | 14 +++++++++----- 4 files changed, 24 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index d01fe53a6638..c8e43e0c4066 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -35,7 +35,6 @@ NESTED(handle_sys, PT_SIZE, sp) lw t1, PT_EPC(sp) # skip syscall on return - subu v0, v0, __NR_O32_Linux # check syscall number addiu t1, 4 # skip to next instruction sw t1, PT_EPC(sp) @@ -89,6 +88,7 @@ loads_done: and t0, t1 bnez t0, syscall_trace_entry # -> yes syscall_common: + subu v0, v0, __NR_O32_Linux # check syscall number sltiu t0, v0, __NR_O32_Linux_syscalls + 1 beqz t0, illegal_syscall @@ -118,24 +118,23 @@ o32_syscall_exit: syscall_trace_entry: SAVE_STATIC - move s0, v0 move a0, sp /* * syscall number is in v0 unless we called syscall(__NR_###) * where the real syscall number is in a0 */ - addiu a1, v0, __NR_O32_Linux - bnez v0, 1f /* __NR_syscall at offset 0 */ + move a1, v0 + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ lw a1, PT_R4(sp) 1: jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move v0, s0 # restore syscall - RESTORE_STATIC + lw v0, PT_R2(sp) # Restore syscall (maybe modified) lw a0, PT_R4(sp) # Restore argument registers lw a1, PT_R5(sp) lw a2, PT_R6(sp) diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 6b73ecc02597..e6ede125059f 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -82,15 +82,14 @@ n64_syscall_exit: syscall_trace_entry: SAVE_STATIC - move s0, v0 move a0, sp move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move v0, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 71f99d5f7a06..9c0b387d6427 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -42,9 +42,6 @@ NESTED(handle_sysn32, PT_SIZE, sp) #endif beqz t0, not_n32_scall - dsll t0, v0, 3 # offset into table - ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) - sd a3, PT_R26(sp) # save a3 for syscall restarting li t1, _TIF_WORK_SYSCALL_ENTRY @@ -53,6 +50,9 @@ NESTED(handle_sysn32, PT_SIZE, sp) bnez t0, n32_syscall_trace_entry syscall_common: + dsll t0, v0, 3 # offset into table + ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) + jalr t2 # Do The Real Thing (TM) li t0, -EMAXERRNO - 1 # error? @@ -71,21 +71,25 @@ syscall_common: n32_syscall_trace_entry: SAVE_STATIC - move s0, t2 move a0, sp move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move t2, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) ld a3, PT_R7(sp) ld a4, PT_R8(sp) ld a5, PT_R9(sp) + + dsubu t2, v0, __NR_N32_Linux # check (new) syscall number + sltiu t0, t2, __NR_N32_Linux_syscalls + 1 + beqz t0, not_n32_scall + j syscall_common 1: j syscall_exit diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 91b43eea2d5a..f4f28b1580de 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -52,9 +52,6 @@ NESTED(handle_sys, PT_SIZE, sp) sll a2, a2, 0 sll a3, a3, 0 - dsll t0, v0, 3 # offset into table - ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0) - sd a3, PT_R26(sp) # save a3 for syscall restarting /* @@ -88,6 +85,9 @@ loads_done: bnez t0, trace_a_syscall syscall_common: + dsll t0, v0, 3 # offset into table + ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0) + jalr t2 # Do The Real Thing (TM) li t0, -EMAXERRNO - 1 # error? @@ -112,7 +112,6 @@ trace_a_syscall: sd a6, PT_R10(sp) sd a7, PT_R11(sp) # For indirect syscalls - move s0, t2 # Save syscall pointer move a0, sp /* * absolute syscall number is in v0 unless we called syscall(__NR_###) @@ -133,8 +132,8 @@ trace_a_syscall: bltz v0, 1f # seccomp failed? Skip syscall - move t2, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) @@ -143,6 +142,11 @@ trace_a_syscall: ld a5, PT_R9(sp) ld a6, PT_R10(sp) ld a7, PT_R11(sp) # For indirect syscalls + + dsubu t0, v0, __NR_O32_Linux # check (new) syscall number + sltiu t0, t0, __NR_O32_Linux_syscalls + 1 + beqz t0, not_o32_scall + j syscall_common 1: j syscall_exit -- cgit v1.2.3-59-g8ed1b From b1b4fad5cc678442c8184a7b91b6cfb0b8b461a5 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Tue, 29 Mar 2016 09:35:33 +0100 Subject: MIPS: seccomp: Support compat with both O32 and N32 Previously the seccomp would only support strict mode on O32 userland programs when the kernel had support for both O32 and N32 ABIs. Remove kludge and support both ABIs. With this patch in place, the seccomp_bpf self test now passes global.mode_strict_support with N32 userland. Suggested-by: Paul Burton Signed-off-by: Matt Redfearn Acked-by: Kees Cook Cc: Andrew Morton Cc: IMG-MIPSLinuxKerneldevelopers@imgtec.com Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12917/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/seccomp.h | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index 1d8a2e2c75c1..684fb3a12ed3 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -2,27 +2,32 @@ #include -/* - * Kludge alert: - * - * The generic seccomp code currently allows only a single compat ABI. Until - * this is fixed we priorize O32 as the compat ABI over N32. - */ -#ifdef CONFIG_MIPS32_O32 - -#define __NR_seccomp_read_32 4003 -#define __NR_seccomp_write_32 4004 -#define __NR_seccomp_exit_32 4001 -#define __NR_seccomp_sigreturn_32 4193 /* rt_sigreturn */ - -#elif defined(CONFIG_MIPS32_N32) - -#define __NR_seccomp_read_32 6000 -#define __NR_seccomp_write_32 6001 -#define __NR_seccomp_exit_32 6058 -#define __NR_seccomp_sigreturn_32 6211 /* rt_sigreturn */ - -#endif /* CONFIG_MIPS32_O32 */ +#ifdef CONFIG_COMPAT +static inline const int *get_compat_mode1_syscalls(void) +{ + static const int syscalls_O32[] = { + __NR_O32_Linux + 3, __NR_O32_Linux + 4, + __NR_O32_Linux + 1, __NR_O32_Linux + 193, + 0, /* null terminated */ + }; + static const int syscalls_N32[] = { + __NR_N32_Linux + 0, __NR_N32_Linux + 1, + __NR_N32_Linux + 58, __NR_N32_Linux + 211, + 0, /* null terminated */ + }; + + if (config_enabled(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS)) + return syscalls_O32; + + if (config_enabled(CONFIG_MIPS32_N32)) + return syscalls_N32; + + BUG(); +} + +#define get_compat_mode1_syscalls get_compat_mode1_syscalls + +#endif /* CONFIG_COMPAT */ #include -- cgit v1.2.3-59-g8ed1b From 766c580356ecca88b32c47b8128bec7d6d014533 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:32 +0100 Subject: MIPS: tools: Add relocs tool This tool is based on the x86/boot/tools/relocs tool. It parses the relocations present in the vmlinux elf file, building a table of relocations that will be necessary to run the kernel from an address other than its link address. This table is inserted into the vmlinux elf, in the .data.relocs section. The table is subsequently used by the code in arch/mips/kernel/relocate.c (added later) to relocate the kernel. The tool, by default, also marks all relocation sections as 0 length. This is due to objcopy currently being unable to handle copying the relocations between 64 and 32 bit elf files as is done when building a 64 bit kernel. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12981/ Signed-off-by: Ralf Baechle --- arch/mips/boot/tools/Makefile | 8 + arch/mips/boot/tools/relocs.c | 680 +++++++++++++++++++++++++++++++++++++ arch/mips/boot/tools/relocs.h | 45 +++ arch/mips/boot/tools/relocs_32.c | 17 + arch/mips/boot/tools/relocs_64.c | 27 ++ arch/mips/boot/tools/relocs_main.c | 84 +++++ 6 files changed, 861 insertions(+) create mode 100644 arch/mips/boot/tools/Makefile create mode 100644 arch/mips/boot/tools/relocs.c create mode 100644 arch/mips/boot/tools/relocs.h create mode 100644 arch/mips/boot/tools/relocs_32.c create mode 100644 arch/mips/boot/tools/relocs_64.c create mode 100644 arch/mips/boot/tools/relocs_main.c (limited to 'arch') diff --git a/arch/mips/boot/tools/Makefile b/arch/mips/boot/tools/Makefile new file mode 100644 index 000000000000..d232a68f6c8a --- /dev/null +++ b/arch/mips/boot/tools/Makefile @@ -0,0 +1,8 @@ + +hostprogs-y += relocs +relocs-objs += relocs_32.o +relocs-objs += relocs_64.o +relocs-objs += relocs_main.o +PHONY += relocs +relocs: $(obj)/relocs + @: diff --git a/arch/mips/boot/tools/relocs.c b/arch/mips/boot/tools/relocs.c new file mode 100644 index 000000000000..b9cbf78527e8 --- /dev/null +++ b/arch/mips/boot/tools/relocs.c @@ -0,0 +1,680 @@ +/* This is included from relocs_32/64.c */ + +#define ElfW(type) _ElfW(ELF_BITS, type) +#define _ElfW(bits, type) __ElfW(bits, type) +#define __ElfW(bits, type) Elf##bits##_##type + +#define Elf_Addr ElfW(Addr) +#define Elf_Ehdr ElfW(Ehdr) +#define Elf_Phdr ElfW(Phdr) +#define Elf_Shdr ElfW(Shdr) +#define Elf_Sym ElfW(Sym) + +static Elf_Ehdr ehdr; + +struct relocs { + uint32_t *offset; + unsigned long count; + unsigned long size; +}; + +static struct relocs relocs; + +struct section { + Elf_Shdr shdr; + struct section *link; + Elf_Sym *symtab; + Elf_Rel *reltab; + char *strtab; + long shdr_offset; +}; +static struct section *secs; + +static const char * const regex_sym_kernel = { +/* Symbols matching these regex's should never be relocated */ + "^(__crc_)", +}; + +static regex_t sym_regex_c; + +static int regex_skip_reloc(const char *sym_name) +{ + return !regexec(&sym_regex_c, sym_name, 0, NULL, 0); +} + +static void regex_init(void) +{ + char errbuf[128]; + int err; + + err = regcomp(&sym_regex_c, regex_sym_kernel, + REG_EXTENDED|REG_NOSUB); + + if (err) { + regerror(err, &sym_regex_c, errbuf, sizeof(errbuf)); + die("%s", errbuf); + } +} + +static const char *rel_type(unsigned type) +{ + static const char * const type_name[] = { +#define REL_TYPE(X)[X] = #X + REL_TYPE(R_MIPS_NONE), + REL_TYPE(R_MIPS_16), + REL_TYPE(R_MIPS_32), + REL_TYPE(R_MIPS_REL32), + REL_TYPE(R_MIPS_26), + REL_TYPE(R_MIPS_HI16), + REL_TYPE(R_MIPS_LO16), + REL_TYPE(R_MIPS_GPREL16), + REL_TYPE(R_MIPS_LITERAL), + REL_TYPE(R_MIPS_GOT16), + REL_TYPE(R_MIPS_PC16), + REL_TYPE(R_MIPS_CALL16), + REL_TYPE(R_MIPS_GPREL32), + REL_TYPE(R_MIPS_64), + REL_TYPE(R_MIPS_HIGHER), + REL_TYPE(R_MIPS_HIGHEST), + REL_TYPE(R_MIPS_PC21_S2), + REL_TYPE(R_MIPS_PC26_S2), +#undef REL_TYPE + }; + const char *name = "unknown type rel type name"; + + if (type < ARRAY_SIZE(type_name) && type_name[type]) + name = type_name[type]; + return name; +} + +static const char *sec_name(unsigned shndx) +{ + const char *sec_strtab; + const char *name; + + sec_strtab = secs[ehdr.e_shstrndx].strtab; + if (shndx < ehdr.e_shnum) + name = sec_strtab + secs[shndx].shdr.sh_name; + else if (shndx == SHN_ABS) + name = "ABSOLUTE"; + else if (shndx == SHN_COMMON) + name = "COMMON"; + else + name = ""; + return name; +} + +static struct section *sec_lookup(const char *secname) +{ + int i; + + for (i = 0; i < ehdr.e_shnum; i++) + if (strcmp(secname, sec_name(i)) == 0) + return &secs[i]; + + return NULL; +} + +static const char *sym_name(const char *sym_strtab, Elf_Sym *sym) +{ + const char *name; + + if (sym->st_name) + name = sym_strtab + sym->st_name; + else + name = sec_name(sym->st_shndx); + return name; +} + +#if BYTE_ORDER == LITTLE_ENDIAN +#define le16_to_cpu(val) (val) +#define le32_to_cpu(val) (val) +#define le64_to_cpu(val) (val) +#define be16_to_cpu(val) bswap_16(val) +#define be32_to_cpu(val) bswap_32(val) +#define be64_to_cpu(val) bswap_64(val) + +#define cpu_to_le16(val) (val) +#define cpu_to_le32(val) (val) +#define cpu_to_le64(val) (val) +#define cpu_to_be16(val) bswap_16(val) +#define cpu_to_be32(val) bswap_32(val) +#define cpu_to_be64(val) bswap_64(val) +#endif +#if BYTE_ORDER == BIG_ENDIAN +#define le16_to_cpu(val) bswap_16(val) +#define le32_to_cpu(val) bswap_32(val) +#define le64_to_cpu(val) bswap_64(val) +#define be16_to_cpu(val) (val) +#define be32_to_cpu(val) (val) +#define be64_to_cpu(val) (val) + +#define cpu_to_le16(val) bswap_16(val) +#define cpu_to_le32(val) bswap_32(val) +#define cpu_to_le64(val) bswap_64(val) +#define cpu_to_be16(val) (val) +#define cpu_to_be32(val) (val) +#define cpu_to_be64(val) (val) +#endif + +static uint16_t elf16_to_cpu(uint16_t val) +{ + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return le16_to_cpu(val); + else + return be16_to_cpu(val); +} + +static uint32_t elf32_to_cpu(uint32_t val) +{ + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return le32_to_cpu(val); + else + return be32_to_cpu(val); +} + +static uint32_t cpu_to_elf32(uint32_t val) +{ + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return cpu_to_le32(val); + else + return cpu_to_be32(val); +} + +#define elf_half_to_cpu(x) elf16_to_cpu(x) +#define elf_word_to_cpu(x) elf32_to_cpu(x) + +#if ELF_BITS == 64 +static uint64_t elf64_to_cpu(uint64_t val) +{ + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return le64_to_cpu(val); + else + return be64_to_cpu(val); +} +#define elf_addr_to_cpu(x) elf64_to_cpu(x) +#define elf_off_to_cpu(x) elf64_to_cpu(x) +#define elf_xword_to_cpu(x) elf64_to_cpu(x) +#else +#define elf_addr_to_cpu(x) elf32_to_cpu(x) +#define elf_off_to_cpu(x) elf32_to_cpu(x) +#define elf_xword_to_cpu(x) elf32_to_cpu(x) +#endif + +static void read_ehdr(FILE *fp) +{ + if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) + die("Cannot read ELF header: %s\n", strerror(errno)); + + if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) + die("No ELF magic\n"); + + if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) + die("Not a %d bit executable\n", ELF_BITS); + + if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) && + (ehdr.e_ident[EI_DATA] != ELFDATA2MSB)) + die("Unknown ELF Endianness\n"); + + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) + die("Unknown ELF version\n"); + + /* Convert the fields to native endian */ + ehdr.e_type = elf_half_to_cpu(ehdr.e_type); + ehdr.e_machine = elf_half_to_cpu(ehdr.e_machine); + ehdr.e_version = elf_word_to_cpu(ehdr.e_version); + ehdr.e_entry = elf_addr_to_cpu(ehdr.e_entry); + ehdr.e_phoff = elf_off_to_cpu(ehdr.e_phoff); + ehdr.e_shoff = elf_off_to_cpu(ehdr.e_shoff); + ehdr.e_flags = elf_word_to_cpu(ehdr.e_flags); + ehdr.e_ehsize = elf_half_to_cpu(ehdr.e_ehsize); + ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize); + ehdr.e_phnum = elf_half_to_cpu(ehdr.e_phnum); + ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize); + ehdr.e_shnum = elf_half_to_cpu(ehdr.e_shnum); + ehdr.e_shstrndx = elf_half_to_cpu(ehdr.e_shstrndx); + + if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) + die("Unsupported ELF header type\n"); + + if (ehdr.e_machine != ELF_MACHINE) + die("Not for %s\n", ELF_MACHINE_NAME); + + if (ehdr.e_version != EV_CURRENT) + die("Unknown ELF version\n"); + + if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) + die("Bad Elf header size\n"); + + if (ehdr.e_phentsize != sizeof(Elf_Phdr)) + die("Bad program header entry\n"); + + if (ehdr.e_shentsize != sizeof(Elf_Shdr)) + die("Bad section header entry\n"); + + if (ehdr.e_shstrndx >= ehdr.e_shnum) + die("String table index out of bounds\n"); +} + +static void read_shdrs(FILE *fp) +{ + int i; + Elf_Shdr shdr; + + secs = calloc(ehdr.e_shnum, sizeof(struct section)); + if (!secs) + die("Unable to allocate %d section headers\n", ehdr.e_shnum); + + if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", ehdr.e_shoff, strerror(errno)); + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + + sec->shdr_offset = ftell(fp); + if (fread(&shdr, sizeof(shdr), 1, fp) != 1) + die("Cannot read ELF section headers %d/%d: %s\n", + i, ehdr.e_shnum, strerror(errno)); + sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name); + sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type); + sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags); + sec->shdr.sh_addr = elf_addr_to_cpu(shdr.sh_addr); + sec->shdr.sh_offset = elf_off_to_cpu(shdr.sh_offset); + sec->shdr.sh_size = elf_xword_to_cpu(shdr.sh_size); + sec->shdr.sh_link = elf_word_to_cpu(shdr.sh_link); + sec->shdr.sh_info = elf_word_to_cpu(shdr.sh_info); + sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign); + sec->shdr.sh_entsize = elf_xword_to_cpu(shdr.sh_entsize); + if (sec->shdr.sh_link < ehdr.e_shnum) + sec->link = &secs[sec->shdr.sh_link]; + } +} + +static void read_strtabs(FILE *fp) +{ + int i; + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + + if (sec->shdr.sh_type != SHT_STRTAB) + continue; + + sec->strtab = malloc(sec->shdr.sh_size); + if (!sec->strtab) + die("malloc of %d bytes for strtab failed\n", + sec->shdr.sh_size); + + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + + if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) != + sec->shdr.sh_size) + die("Cannot read symbol table: %s\n", strerror(errno)); + } +} + +static void read_symtabs(FILE *fp) +{ + int i, j; + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + if (sec->shdr.sh_type != SHT_SYMTAB) + continue; + + sec->symtab = malloc(sec->shdr.sh_size); + if (!sec->symtab) + die("malloc of %d bytes for symtab failed\n", + sec->shdr.sh_size); + + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + + if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) != + sec->shdr.sh_size) + die("Cannot read symbol table: %s\n", strerror(errno)); + + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) { + Elf_Sym *sym = &sec->symtab[j]; + + sym->st_name = elf_word_to_cpu(sym->st_name); + sym->st_value = elf_addr_to_cpu(sym->st_value); + sym->st_size = elf_xword_to_cpu(sym->st_size); + sym->st_shndx = elf_half_to_cpu(sym->st_shndx); + } + } +} + +static void read_relocs(FILE *fp) +{ + static unsigned long base = 0; + int i, j; + + if (!base) { + struct section *sec = sec_lookup(".text"); + + if (!sec) + die("Could not find .text section\n"); + + base = sec->shdr.sh_addr; + } + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + + if (sec->shdr.sh_type != SHT_REL_TYPE) + continue; + + sec->reltab = malloc(sec->shdr.sh_size); + if (!sec->reltab) + die("malloc of %d bytes for relocs failed\n", + sec->shdr.sh_size); + + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + + if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) != + sec->shdr.sh_size) + die("Cannot read symbol table: %s\n", strerror(errno)); + + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { + Elf_Rel *rel = &sec->reltab[j]; + + rel->r_offset = elf_addr_to_cpu(rel->r_offset); + /* Set offset into kernel image */ + rel->r_offset -= base; +#if (ELF_BITS == 32) + rel->r_info = elf_xword_to_cpu(rel->r_info); +#else + /* Convert MIPS64 RELA format - only the symbol + * index needs converting to native endianness + */ + rel->r_info = rel->r_info; + ELF_R_SYM(rel->r_info) = elf32_to_cpu(ELF_R_SYM(rel->r_info)); +#endif +#if (SHT_REL_TYPE == SHT_RELA) + rel->r_addend = elf_xword_to_cpu(rel->r_addend); +#endif + } + } +} + +static void remove_relocs(FILE *fp) +{ + int i; + Elf_Shdr shdr; + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + + if (sec->shdr.sh_type != SHT_REL_TYPE) + continue; + + if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", + sec->shdr_offset, strerror(errno)); + + if (fread(&shdr, sizeof(shdr), 1, fp) != 1) + die("Cannot read ELF section headers %d/%d: %s\n", + i, ehdr.e_shnum, strerror(errno)); + + /* Set relocation section size to 0, effectively removing it. + * This is necessary due to lack of support for relocations + * in objcopy when creating 32bit elf from 64bit elf. + */ + shdr.sh_size = 0; + + if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0) + die("Seek to %d failed: %s\n", + sec->shdr_offset, strerror(errno)); + + if (fwrite(&shdr, sizeof(shdr), 1, fp) != 1) + die("Cannot write ELF section headers %d/%d: %s\n", + i, ehdr.e_shnum, strerror(errno)); + } +} + +static void add_reloc(struct relocs *r, uint32_t offset, unsigned type) +{ + /* Relocation representation in binary table: + * |76543210|76543210|76543210|76543210| + * | Type | offset from _text >> 2 | + */ + offset >>= 2; + if (offset > 0x00FFFFFF) + die("Kernel image exceeds maximum size for relocation!\n"); + + offset = (offset & 0x00FFFFFF) | ((type & 0xFF) << 24); + + if (r->count == r->size) { + unsigned long newsize = r->size + 50000; + void *mem = realloc(r->offset, newsize * sizeof(r->offset[0])); + + if (!mem) + die("realloc failed\n"); + + r->offset = mem; + r->size = newsize; + } + r->offset[r->count++] = offset; +} + +static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, + Elf_Sym *sym, const char *symname)) +{ + int i; + + /* Walk through the relocations */ + for (i = 0; i < ehdr.e_shnum; i++) { + char *sym_strtab; + Elf_Sym *sh_symtab; + struct section *sec_applies, *sec_symtab; + int j; + struct section *sec = &secs[i]; + + if (sec->shdr.sh_type != SHT_REL_TYPE) + continue; + + sec_symtab = sec->link; + sec_applies = &secs[sec->shdr.sh_info]; + if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) + continue; + + sh_symtab = sec_symtab->symtab; + sym_strtab = sec_symtab->link->strtab; + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { + Elf_Rel *rel = &sec->reltab[j]; + Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)]; + const char *symname = sym_name(sym_strtab, sym); + + process(sec, rel, sym, symname); + } + } +} + +static int do_reloc(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, + const char *symname) +{ + unsigned r_type = ELF_R_TYPE(rel->r_info); + unsigned bind = ELF_ST_BIND(sym->st_info); + + if ((bind == STB_WEAK) && (sym->st_value == 0)) { + /* Don't relocate weak symbols without a target */ + return 0; + } + + if (regex_skip_reloc(symname)) + return 0; + + switch (r_type) { + case R_MIPS_NONE: + case R_MIPS_REL32: + case R_MIPS_PC16: + case R_MIPS_PC21_S2: + case R_MIPS_PC26_S2: + /* + * NONE can be ignored and PC relative relocations don't + * need to be adjusted. + */ + case R_MIPS_HIGHEST: + case R_MIPS_HIGHER: + /* We support relocating within the same 4Gb segment only, + * thus leaving the top 32bits unchanged + */ + case R_MIPS_LO16: + /* We support relocating by 64k jumps only + * thus leaving the bottom 16bits unchanged + */ + break; + + case R_MIPS_64: + case R_MIPS_32: + case R_MIPS_26: + case R_MIPS_HI16: + add_reloc(&relocs, rel->r_offset, r_type); + break; + + default: + die("Unsupported relocation type: %s (%d)\n", + rel_type(r_type), r_type); + break; + } + + return 0; +} + +static int write_reloc_as_bin(uint32_t v, FILE *f) +{ + unsigned char buf[4]; + + v = cpu_to_elf32(v); + + memcpy(buf, &v, sizeof(uint32_t)); + return fwrite(buf, 1, 4, f); +} + +static int write_reloc_as_text(uint32_t v, FILE *f) +{ + int res; + + res = fprintf(f, "\t.long 0x%08"PRIx32"\n", v); + if (res < 0) + return res; + else + return sizeof(uint32_t); +} + +static void emit_relocs(int as_text, int as_bin, FILE *outf) +{ + int i; + int (*write_reloc)(uint32_t, FILE *) = write_reloc_as_bin; + int size = 0; + int size_reserved; + struct section *sec_reloc; + + sec_reloc = sec_lookup(".data.reloc"); + if (!sec_reloc) + die("Could not find relocation section\n"); + + size_reserved = sec_reloc->shdr.sh_size; + + /* Collect up the relocations */ + walk_relocs(do_reloc); + + /* Print the relocations */ + if (as_text) { + /* Print the relocations in a form suitable that + * gas will like. + */ + printf(".section \".data.reloc\",\"a\"\n"); + printf(".balign 4\n"); + /* Output text to stdout */ + write_reloc = write_reloc_as_text; + outf = stdout; + } else if (as_bin) { + /* Output raw binary to stdout */ + outf = stdout; + } else { + /* Seek to offset of the relocation section. + * Each relocation is then written into the + * vmlinux kernel image. + */ + if (fseek(outf, sec_reloc->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec_reloc->shdr.sh_offset, strerror(errno)); + } + } + + for (i = 0; i < relocs.count; i++) + size += write_reloc(relocs.offset[i], outf); + + /* Print a stop, but only if we've actually written some relocs */ + if (size) + size += write_reloc(0, outf); + + if (size > size_reserved) + /* Die, but suggest a value for CONFIG_RELOCATION_TABLE_SIZE + * which will fix this problem and allow a bit of headroom + * if more kernel features are enabled + */ + die("Relocations overflow available space!\n" \ + "Please adjust CONFIG_RELOCATION_TABLE_SIZE " \ + "to at least 0x%08x\n", (size + 0x1000) & ~0xFFF); +} + +/* + * As an aid to debugging problems with different linkers + * print summary information about the relocs. + * Since different linkers tend to emit the sections in + * different orders we use the section names in the output. + */ +static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, + const char *symname) +{ + printf("%16s 0x%08x %16s %40s %16s\n", + sec_name(sec->shdr.sh_info), + (unsigned int)rel->r_offset, + rel_type(ELF_R_TYPE(rel->r_info)), + symname, + sec_name(sym->st_shndx)); + return 0; +} + +static void print_reloc_info(void) +{ + printf("%16s %10s %16s %40s %16s\n", + "reloc section", + "offset", + "reloc type", + "symbol", + "symbol section"); + walk_relocs(do_reloc_info); +} + +#if ELF_BITS == 64 +# define process process_64 +#else +# define process process_32 +#endif + +void process(FILE *fp, int as_text, int as_bin, + int show_reloc_info, int keep_relocs) +{ + regex_init(); + read_ehdr(fp); + read_shdrs(fp); + read_strtabs(fp); + read_symtabs(fp); + read_relocs(fp); + if (show_reloc_info) { + print_reloc_info(); + return; + } + emit_relocs(as_text, as_bin, fp); + if (!keep_relocs) + remove_relocs(fp); +} diff --git a/arch/mips/boot/tools/relocs.h b/arch/mips/boot/tools/relocs.h new file mode 100644 index 000000000000..3cf676f49e18 --- /dev/null +++ b/arch/mips/boot/tools/relocs.h @@ -0,0 +1,45 @@ +#ifndef RELOCS_H +#define RELOCS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define USE_BSD +#include +#include + +void die(char *fmt, ...); + +/* + * Introduced for MIPSr6 + */ +#ifndef R_MIPS_PC21_S2 +#define R_MIPS_PC21_S2 60 +#endif + +#ifndef R_MIPS_PC26_S2 +#define R_MIPS_PC26_S2 61 +#endif + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +enum symtype { + S_ABS, + S_REL, + S_SEG, + S_LIN, + S_NSYMTYPES +}; + +void process_32(FILE *fp, int as_text, int as_bin, + int show_reloc_info, int keep_relocs); +void process_64(FILE *fp, int as_text, int as_bin, + int show_reloc_info, int keep_relocs); +#endif /* RELOCS_H */ diff --git a/arch/mips/boot/tools/relocs_32.c b/arch/mips/boot/tools/relocs_32.c new file mode 100644 index 000000000000..915bdc07f5ed --- /dev/null +++ b/arch/mips/boot/tools/relocs_32.c @@ -0,0 +1,17 @@ +#include "relocs.h" + +#define ELF_BITS 32 + +#define ELF_MACHINE EM_MIPS +#define ELF_MACHINE_NAME "MIPS" +#define SHT_REL_TYPE SHT_REL +#define Elf_Rel ElfW(Rel) + +#define ELF_CLASS ELFCLASS32 +#define ELF_R_SYM(val) ELF32_R_SYM(val) +#define ELF_R_TYPE(val) ELF32_R_TYPE(val) +#define ELF_ST_TYPE(o) ELF32_ST_TYPE(o) +#define ELF_ST_BIND(o) ELF32_ST_BIND(o) +#define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) + +#include "relocs.c" diff --git a/arch/mips/boot/tools/relocs_64.c b/arch/mips/boot/tools/relocs_64.c new file mode 100644 index 000000000000..b671b5e2dcd8 --- /dev/null +++ b/arch/mips/boot/tools/relocs_64.c @@ -0,0 +1,27 @@ +#include "relocs.h" + +#define ELF_BITS 64 + +#define ELF_MACHINE EM_MIPS +#define ELF_MACHINE_NAME "MIPS64" +#define SHT_REL_TYPE SHT_RELA +#define Elf_Rel Elf64_Rela + +typedef uint8_t Elf64_Byte; + +typedef struct { + Elf64_Word r_sym; /* Symbol index. */ + Elf64_Byte r_ssym; /* Special symbol. */ + Elf64_Byte r_type3; /* Third relocation. */ + Elf64_Byte r_type2; /* Second relocation. */ + Elf64_Byte r_type; /* First relocation. */ +} Elf64_Mips_Rela; + +#define ELF_CLASS ELFCLASS64 +#define ELF_R_SYM(val) (((Elf64_Mips_Rela *)(&val))->r_sym) +#define ELF_R_TYPE(val) (((Elf64_Mips_Rela *)(&val))->r_type) +#define ELF_ST_TYPE(o) ELF64_ST_TYPE(o) +#define ELF_ST_BIND(o) ELF64_ST_BIND(o) +#define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o) + +#include "relocs.c" diff --git a/arch/mips/boot/tools/relocs_main.c b/arch/mips/boot/tools/relocs_main.c new file mode 100644 index 000000000000..d8fe2343b8d0 --- /dev/null +++ b/arch/mips/boot/tools/relocs_main.c @@ -0,0 +1,84 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "relocs.h" + +void die(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static void usage(void) +{ + die("relocs [--reloc-info|--text|--bin|--keep] vmlinux\n"); +} + +int main(int argc, char **argv) +{ + int show_reloc_info, as_text, as_bin, keep_relocs; + const char *fname; + FILE *fp; + int i; + unsigned char e_ident[EI_NIDENT]; + + show_reloc_info = 0; + as_text = 0; + as_bin = 0; + keep_relocs = 0; + fname = NULL; + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + + if (*arg == '-') { + if (strcmp(arg, "--reloc-info") == 0) { + show_reloc_info = 1; + continue; + } + if (strcmp(arg, "--text") == 0) { + as_text = 1; + continue; + } + if (strcmp(arg, "--bin") == 0) { + as_bin = 1; + continue; + } + if (strcmp(arg, "--keep") == 0) { + keep_relocs = 1; + continue; + } + } else if (!fname) { + fname = arg; + continue; + } + usage(); + } + if (!fname) + usage(); + + fp = fopen(fname, "r+"); + if (!fp) + die("Cannot open %s: %s\n", fname, strerror(errno)); + + if (fread(&e_ident, 1, EI_NIDENT, fp) != EI_NIDENT) + die("Cannot read %s: %s", fname, strerror(errno)); + + rewind(fp); + if (e_ident[EI_CLASS] == ELFCLASS64) + process_64(fp, as_text, as_bin, show_reloc_info, keep_relocs); + else + process_32(fp, as_text, as_bin, show_reloc_info, keep_relocs); + fclose(fp); + return 0; +} -- cgit v1.2.3-59-g8ed1b From aadeec4df9b33526f45a27e61df6891dd21b1e39 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:33 +0100 Subject: MIPS: tools: Build relocs tool Build the relocs tool as part of the kbuild Signed-off-by: Matt Redfearn Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12980/ Patchwork: https://patchwork.linux-mips.org/patch/13242/ Patchwork: https://patchwork.linux-mips.org/patch/13233/ Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 4 ++++ arch/mips/boot/tools/.gitignore | 1 + 2 files changed, 5 insertions(+) create mode 100644 arch/mips/boot/tools/.gitignore (limited to 'arch') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index e78d60dbdffd..a61031e7c06f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -12,6 +12,9 @@ # for "archclean" cleaning up for this architecture. # +archscripts: scripts_basic + $(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs + KBUILD_DEFCONFIG := ip22_defconfig # @@ -385,6 +388,7 @@ endif archclean: $(Q)$(MAKE) $(clean)=arch/mips/boot $(Q)$(MAKE) $(clean)=arch/mips/boot/compressed + $(Q)$(MAKE) $(clean)=arch/mips/boot/tools $(Q)$(MAKE) $(clean)=arch/mips/lasat define archhelp diff --git a/arch/mips/boot/tools/.gitignore b/arch/mips/boot/tools/.gitignore new file mode 100644 index 000000000000..be0ed065249b --- /dev/null +++ b/arch/mips/boot/tools/.gitignore @@ -0,0 +1 @@ +relocs -- cgit v1.2.3-59-g8ed1b From 069fd766271de65ec4dc2eb8d15f7f44727b1ea1 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:34 +0100 Subject: MIPS: Reserve space for relocation table When CONFIG_RELOCATABLE is enabled, add a new section in the memory map to be filled with relocation data. CONFIG_RELOCATION_TABLE_SIZE allows the amount of space reserved to be adjusted if necessary. The relocs tool will populate this reserved space with relocation information. The space is reserved within the elf by filling it with 0's, and an invalid entry is left at the start of the space such that kernel relocation will be aborted if the table is empty. Signed-off-by: Matt Redfearn Cc: Aaro Koskinen Cc: David Daney Cc: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12982/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 16 ++++++++++++++++ arch/mips/kernel/vmlinux.lds.S | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b5609111a3bd..99ec21f35433 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2473,6 +2473,22 @@ config NUMA config SYS_SUPPORTS_NUMA bool +config RELOCATION_TABLE_SIZE + hex "Relocation table size" + depends on RELOCATABLE + range 0x0 0x01000000 + default "0x00100000" + ---help--- + A table of relocation data will be appended to the kernel binary + and parsed at boot to fix up the relocated kernel. + + This option allows the amount of space reserved for the table to be + adjusted, although the default of 1Mb should be ok in most cases. + + The build will fail and a valid size suggested if this is too small. + + If unsure, leave at the default value. + config NODES_SHIFT int default "6" diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 54d653ee17e1..a82c178d0bb9 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -136,6 +136,27 @@ SECTIONS #ifdef CONFIG_SMP PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT) #endif + +#ifdef CONFIG_RELOCATABLE + . = ALIGN(4); + + .data.reloc : { + _relocation_start = .; + /* + * Space for relocation table + * This needs to be filled so that the + * relocs tool can overwrite the content. + * An invalid value is left at the start of the + * section to abort relocation if the table + * has not been filled in. + */ + LONG(0xFFFFFFFF); + FILL(0); + . += CONFIG_RELOCATION_TABLE_SIZE - 4; + _relocation_end = .; + } +#endif + #ifdef CONFIG_MIPS_RAW_APPENDED_DTB __appended_dtb = .; /* leave space for appended DTB */ -- cgit v1.2.3-59-g8ed1b From e818fac595ab94900f0046baba1f1a0e2d5c2435 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:35 +0100 Subject: MIPS: Generate relocation table when CONFIG_RELOCATABLE When CONFIG_RELOCATABLE is enabled (added in later patch) add --emit-relocs to vmlinux LDFLAGS so that fully linked vmlinux contains relocation information. Run the previously added relocs tool to fill in the .data.relocs section of vmlinux with a table of relocations. The relocs tool will also remove (mark as 0 length) the relocation sections added to vmlinux. When vmlinux is passed to the boot makefile for conversion into a boot image the now empty relocation sections will be removed and the populated relocation table will be included in the binary image. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12983/ Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a61031e7c06f..c0b002a09bef 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -96,6 +96,10 @@ LDFLAGS_vmlinux += -G 0 -static -n -nostdlib KBUILD_AFLAGS_MODULE += -mlong-calls KBUILD_CFLAGS_MODULE += -mlong-calls +ifeq ($(CONFIG_RELOCATABLE),y) +LDFLAGS_vmlinux += --emit-relocs +endif + # # pass -msoft-float to GAS if it supports it. However on newer binutils # (specifically newer than 2.24.51.20140728) we then also need to explicitly @@ -313,6 +317,10 @@ rom.bin rom.sw: vmlinux $(bootvars-y) $@ endif +CMD_RELOCS = arch/mips/boot/tools/relocs +quiet_cmd_relocs = RELOCS $< + cmd_relocs = $(CMD_RELOCS) $< + # # Some machines like the Indy need 32-bit ELF binaries for booting purposes. # Other need ECOFF, so we build a 32-bit ELF binary for them which we then @@ -321,6 +329,11 @@ endif quiet_cmd_32 = OBJCOPY $@ cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ vmlinux.32: vmlinux +ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_64BIT),yy) +# Currently, objcopy fails to handle the relocations in the elf64 +# So the relocs tool must be run here to remove them first + $(call cmd,relocs) +endif $(call cmd,32) # @@ -336,6 +349,9 @@ all: $(all-y) # boot $(boot-y): $(vmlinux-32) FORCE +ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_32BIT),yy) + $(call cmd,relocs) +endif $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \ $(bootvars-y) arch/mips/boot/$@ -- cgit v1.2.3-59-g8ed1b From 279b991b24d2439fbe9d2f093988b9c8aed2603d Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:36 +0100 Subject: MIPS: Kernel: Add relocate.c arch/mips/kernel/relocate.c contains the functions necessary to relocate the kernel elsewhere in memory The kernel makes a copy of itself at the new address. It uses the relocation table inserted by the relocs tool to fix symbol references within the new image. If copy/relocation is sucessful then the entry point of the new kernel is returned, otherwise fall back to starting the kernel in place. Signed-off-by: Matt Redfearn Cc: Thomas Gleixner Cc: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12985/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/Makefile | 2 + arch/mips/kernel/relocate.c | 240 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 arch/mips/kernel/relocate.c (limited to 'arch') diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 8a8b775fa7c8..e6053d07072f 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -83,6 +83,8 @@ obj-$(CONFIG_I8253) += i8253.o obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o +obj-$(CONFIG_RELOCATABLE) += relocate.o + obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c new file mode 100644 index 000000000000..742cc7a50dad --- /dev/null +++ b/arch/mips/kernel/relocate.c @@ -0,0 +1,240 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Support for Kernel relocation at boot time + * + * Copyright (C) 2015, Imagination Technologies Ltd. + * Authors: Matt Redfearn (matt.redfearn@imgtec.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RELOCATED(x) ((void *)((long)x + offset)) + +extern u32 _relocation_start[]; /* End kernel image / start relocation table */ +extern u32 _relocation_end[]; /* End relocation table */ + +extern long __start___ex_table; /* Start exception table */ +extern long __stop___ex_table; /* End exception table */ + +static inline u32 __init get_synci_step(void) +{ + u32 res; + + __asm__("rdhwr %0, $1" : "=r" (res)); + + return res; +} + +static void __init sync_icache(void *kbase, unsigned long kernel_length) +{ + void *kend = kbase + kernel_length; + u32 step = get_synci_step(); + + do { + __asm__ __volatile__( + "synci 0(%0)" + : /* no output */ + : "r" (kbase)); + + kbase += step; + } while (kbase < kend); + + /* Completion barrier */ + __sync(); +} + +static int __init apply_r_mips_64_rel(u32 *loc_orig, u32 *loc_new, long offset) +{ + *(u64 *)loc_new += offset; + + return 0; +} + +static int __init apply_r_mips_32_rel(u32 *loc_orig, u32 *loc_new, long offset) +{ + *loc_new += offset; + + return 0; +} + +static int __init apply_r_mips_26_rel(u32 *loc_orig, u32 *loc_new, long offset) +{ + unsigned long target_addr = (*loc_orig) & 0x03ffffff; + + if (offset % 4) { + pr_err("Dangerous R_MIPS_26 REL relocation\n"); + return -ENOEXEC; + } + + /* Original target address */ + target_addr <<= 2; + target_addr += (unsigned long)loc_orig & ~0x03ffffff; + + /* Get the new target address */ + target_addr += offset; + + if ((target_addr & 0xf0000000) != ((unsigned long)loc_new & 0xf0000000)) { + pr_err("R_MIPS_26 REL relocation overflow\n"); + return -ENOEXEC; + } + + target_addr -= (unsigned long)loc_new & ~0x03ffffff; + target_addr >>= 2; + + *loc_new = (*loc_new & ~0x03ffffff) | (target_addr & 0x03ffffff); + + return 0; +} + + +static int __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new, long offset) +{ + unsigned long insn = *loc_orig; + unsigned long target = (insn & 0xffff) << 16; /* high 16bits of target */ + + target += offset; + + *loc_new = (insn & ~0xffff) | ((target >> 16) & 0xffff); + return 0; +} + +static int (*reloc_handlers_rel[]) (u32 *, u32 *, long) __initdata = { + [R_MIPS_64] = apply_r_mips_64_rel, + [R_MIPS_32] = apply_r_mips_32_rel, + [R_MIPS_26] = apply_r_mips_26_rel, + [R_MIPS_HI16] = apply_r_mips_hi16_rel, +}; + +int __init do_relocations(void *kbase_old, void *kbase_new, long offset) +{ + u32 *r; + u32 *loc_orig; + u32 *loc_new; + int type; + int res; + + for (r = _relocation_start; r < _relocation_end; r++) { + /* Sentinel for last relocation */ + if (*r == 0) + break; + + type = (*r >> 24) & 0xff; + loc_orig = (void *)(kbase_old + ((*r & 0x00ffffff) << 2)); + loc_new = RELOCATED(loc_orig); + + if (reloc_handlers_rel[type] == NULL) { + /* Unsupported relocation */ + pr_err("Unhandled relocation type %d at 0x%pK\n", + type, loc_orig); + return -ENOEXEC; + } + + res = reloc_handlers_rel[type](loc_orig, loc_new, offset); + if (res) + return res; + } + + return 0; +} + +/* + * The exception table is filled in by the relocs tool after vmlinux is linked. + * It must be relocated separately since there will not be any relocation + * information for it filled in by the linker. + */ +static int __init relocate_exception_table(long offset) +{ + unsigned long *etable_start, *etable_end, *e; + + etable_start = RELOCATED(&__start___ex_table); + etable_end = RELOCATED(&__stop___ex_table); + + for (e = etable_start; e < etable_end; e++) + *e += offset; + + return 0; +} + +static inline void __init *determine_relocation_address(void) +{ + /* + * Choose a new address for the kernel + * For now we'll hard code the destination + */ + return (void *)0xffffffff81000000; +} + +static inline int __init relocation_addr_valid(void *loc_new) +{ + if ((unsigned long)loc_new & 0x0000ffff) { + /* Inappropriately aligned new location */ + return 0; + } + if ((unsigned long)loc_new < (unsigned long)&_end) { + /* New location overlaps original kernel */ + return 0; + } + return 1; +} + +void *__init relocate_kernel(void) +{ + void *loc_new; + unsigned long kernel_length; + unsigned long bss_length; + long offset = 0; + int res = 1; + /* Default to original kernel entry point */ + void *kernel_entry = start_kernel; + + kernel_length = (long)(&_relocation_start) - (long)(&_text); + bss_length = (long)&__bss_stop - (long)&__bss_start; + + loc_new = determine_relocation_address(); + + /* Sanity check relocation address */ + if (relocation_addr_valid(loc_new)) + offset = (unsigned long)loc_new - (unsigned long)(&_text); + + if (offset) { + /* Copy the kernel to it's new location */ + memcpy(loc_new, &_text, kernel_length); + + /* Perform relocations on the new kernel */ + res = do_relocations(&_text, loc_new, offset); + if (res < 0) + goto out; + + /* Sync the caches ready for execution of new kernel */ + sync_icache(loc_new, kernel_length); + + res = relocate_exception_table(offset); + if (res < 0) + goto out; + + /* + * The original .bss has already been cleared, and + * some variables such as command line parameters + * stored to it so make a copy in the new location. + */ + memcpy(RELOCATED(&__bss_start), &__bss_start, bss_length); + + /* The current thread is now within the relocated image */ + __current_thread_info = RELOCATED(&init_thread_union); + + /* Return the new kernel's entry point */ + kernel_entry = RELOCATED(start_kernel); + } +out: + return kernel_entry; +} -- cgit v1.2.3-59-g8ed1b From af09ab5e3fa7b6e137b135325a2ca00d57b4aea2 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:37 +0100 Subject: MIPS: Call relocate_kernel if CONFIG_RELOCATABLE=y If CONFIG_RELOCATABLE is enabled, call relocate_kernel. This function will return the entry point of the relocated kernel if copy/relocate is sucessful or the original entry point if not. The stack pointer must then be pointed into the new image. Signed-off-by: Matt Redfearn Cc: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12984/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/head.S | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 4e4cc5b9a771..7dc043349d66 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -132,7 +132,27 @@ not_found: set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer +#ifdef CONFIG_RELOCATABLE + /* Copy kernel and apply the relocations */ + jal relocate_kernel + + /* Repoint the sp into the new kernel image */ + PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE + PTR_ADDU sp, $28 + set_saved_sp sp, t0, t1 + PTR_SUBU sp, 4 * SZREG # init stack pointer + + /* + * relocate_kernel returns the entry point either + * in the relocated kernel or the original if for + * some reason relocation failed - jump there now + * with instruction hazard barrier because of the + * newly sync'd icache. + */ + jr.hb v0 +#else j start_kernel +#endif END(kernel_entry) #ifdef CONFIG_SMP -- cgit v1.2.3-59-g8ed1b From 61cd52d4e44d7d8c55dad939b1877fd39d7103a2 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:38 +0100 Subject: MIPS: bootmem: When relocatable, free memory below kernel The kernel reserves all memory before the _end symbol as bootmem, however, once the kernel can be relocated elsewhere in memory this may result in a large amount of wasted memory. The assumption is that the memory between the link and relocated address of the kernel may be released back to the available memory pool. Memory statistics for a Malta with the kernel relocating by 16Mb, without the patch: Memory: 105952K/131072K available (4604K kernel code, 242K rwdata, 892K rodata, 1280K init, 183K bss, 25120K reserved, 0K cma-reserved) And with the patch: Memory: 122336K/131072K available (4604K kernel code, 242K rwdata, 892K rodata, 1280K init, 183K bss, 8736K reserved, 0K cma-reserved) The 16Mb offset is removed from the reserved region and added back to the available region. Signed-off-by: Matt Redfearn Cc: Aaro Koskinen Cc: Masahiro Yamada Cc: Alexander Sverdlin Cc: Jaedon Shin Cc: James Hogan Cc: Jonas Gorski Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12986/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index d20caacfdbd3..3378fdaf4dd3 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -469,6 +469,20 @@ static void __init bootmem_init(void) */ reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT); +#ifdef CONFIG_RELOCATABLE + /* + * The kernel reserves all memory below its _end symbol as bootmem, + * but the kernel may now be at a much higher address. The memory + * between the original and new locations may be returned to the system. + */ + if (__pa_symbol(_text) > __pa_symbol(VMLINUX_LOAD_ADDRESS)) { + unsigned long offset; + + offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS); + free_bootmem(__pa_symbol(VMLINUX_LOAD_ADDRESS), offset); + } +#endif + /* * Reserve initrd memory if needed. */ -- cgit v1.2.3-59-g8ed1b From 8c530ea35caef8bc293b56580ab55352f7d86bfc Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:39 +0100 Subject: MIPS: Add CONFIG_RELOCATABLE Kconfig option Add option to KConfig to enable the kernel to relocate itself at runtime. Relocation is supported R2 and later of the MIPS architecture, 32bit and 64bit. The platform is also required to provide support through plat_get_fdt() added in a later patch. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12987/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 99ec21f35433..7040a6bcc74f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -475,6 +475,7 @@ config MIPS_MALTA select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_RELOCATABLE select USE_OF select ZONE_DMA32 if 64BIT select BUILTIN_DTB @@ -519,6 +520,7 @@ config MIPS_SEAD3 select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_MICROMIPS select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_RELOCATABLE select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO select USE_OF @@ -1158,6 +1160,13 @@ config ISA_DMA_API config HOLES_IN_ZONE bool +config SYS_SUPPORTS_RELOCATABLE + bool + help + Selected if the platform supports relocating the kernel. + The platform must provide plat_get_fdt() if it selects CONFIG_USE_OF + to allow access to command line and entropy sources. + # # Endianness selection. Sufficiently obscure so many users don't know what to # answer,so we try hard to limit the available choices. Also the use of a @@ -2473,6 +2482,15 @@ config NUMA config SYS_SUPPORTS_NUMA bool +config RELOCATABLE + bool "Relocatable kernel" + depends on SYS_SUPPORTS_RELOCATABLE && (CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_MIPS32_R6 || CPU_MIPS64_R6) + help + This builds a kernel image that retains relocation information + so it can be loaded someplace besides the default 1MB. + The relocations make the kernel binary about 15% larger, + but are discarded at runtime + config RELOCATION_TABLE_SIZE hex "Relocation table size" depends on RELOCATABLE -- cgit v1.2.3-59-g8ed1b From 5e7c1c918a4433c5dd1844d99f5648e17425fa16 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:40 +0100 Subject: MIPS: Introduce plat_get_fdt a platform API to retrieve the FDT Early access to the kernel command line requires early access to the FDT for platforms which pass the command line within the device tree. There was no common way to retrieve the location of the FDT without incurring side effects, such as plat_mem_setup which, on Malta at least, initializes a bunch of other stuff. This patch adds plat_get_ftd() for IMG platforms. Signed-off-by: Matt Redfearn Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12988/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/bootinfo.h | 18 ++++++++++++++++++ arch/mips/mti-malta/malta-setup.c | 7 ++++++- arch/mips/mti-sead3/sead3-setup.c | 5 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h index b603804caac5..9f67033961a6 100644 --- a/arch/mips/include/asm/bootinfo.h +++ b/arch/mips/include/asm/bootinfo.h @@ -144,4 +144,22 @@ static inline void plat_swiotlb_setup(void) {} #endif /* CONFIG_SWIOTLB */ +#ifdef CONFIG_USE_OF +/** + * plat_get_fdt() - Return a pointer to the platform's device tree blob + * + * This function provides a platform independent API to get a pointer to the + * flattened device tree blob. The interface between bootloader and kernel + * is not consistent across platforms so it is necessary to provide this + * API such that common startup code can locate the FDT. + * + * This is used by the KASLR code to get command line arguments and random + * seed from the device tree. Any platform wishing to use KASLR should + * provide this API and select SYS_SUPPORTS_RELOCATABLE. + * + * Return: Pointer to the flattened device tree blob. + */ +extern void *plat_get_fdt(void); +#endif /* CONFIG_USE_OF */ + #endif /* _ASM_BOOTINFO_H */ diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index 4740c82fb97a..33d5ff5069e5 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -248,10 +248,15 @@ static void __init bonito_quirks_setup(void) #endif } +void __init *plat_get_fdt(void) +{ + return (void *)__dtb_start; +} + void __init plat_mem_setup(void) { unsigned int i; - void *fdt = __dtb_start; + void *fdt = plat_get_fdt(); fdt = malta_dt_shim(fdt); __dt_setup_arch(fdt); diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c index e43f4801a245..9f2f9b2b23ce 100644 --- a/arch/mips/mti-sead3/sead3-setup.c +++ b/arch/mips/mti-sead3/sead3-setup.c @@ -83,6 +83,11 @@ static void __init parse_memsize_param(void) } } +void __init *plat_get_fdt(void) +{ + return (void *)__dtb_start; +} + void __init plat_mem_setup(void) { /* allow command line/bootloader env to override memory size in DT */ -- cgit v1.2.3-59-g8ed1b From 405bc8fd12f59ec865714447b2f6e1a961f49025 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:41 +0100 Subject: MIPS: Kernel: Implement KASLR using CONFIG_RELOCATABLE This patch adds KASLR to the MIPS kernel. Entropy is derived from the banner, which will change every build and random_get_entropy() which should provide additional runtime entropy. Additionally the bootloader may pass entropy via the /chosen/kaslr-seed node in device tree. The kernel is relocated by up to RANDOMIZE_BASE_MAX_OFFSET bytes from its link address (PHYSICAL_START). Because relocation happens so early in the kernel boot, the amount of physical memory has not yet been determined. This means the only way to limit relocation within the available memory is via Kconfig. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12990/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 30 +++++++++ arch/mips/kernel/relocate.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7040a6bcc74f..68ddb45d6258 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2507,6 +2507,36 @@ config RELOCATION_TABLE_SIZE If unsure, leave at the default value. +config RANDOMIZE_BASE + bool "Randomize the address of the kernel image" + depends on RELOCATABLE + ---help--- + Randomizes the physical and virtual address at which the + kernel image is loaded, as a security feature that + deters exploit attempts relying on knowledge of the location + of kernel internals. + + Entropy is generated using any coprocessor 0 registers available. + + The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET. + + If unsure, say N. + +config RANDOMIZE_BASE_MAX_OFFSET + hex "Maximum kASLR offset" if EXPERT + depends on RANDOMIZE_BASE + range 0x0 0x40000000 if EVA || 64BIT + range 0x0 0x08000000 + default "0x01000000" + ---help--- + When kASLR is active, this provides the maximum offset that will + be applied to the kernel image. It should be set according to the + amount of physical RAM available in the target system minus + PHYSICAL_START and must be a power of 2. + + This is limited by the size of KSEG0, 256Mb on 32-bit or 1Gb with + EVA or 64-bit. The default is 16Mb. + config NODES_SHIFT int default "6" diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 742cc7a50dad..ca1cc30c0891 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -8,15 +8,20 @@ * Copyright (C) 2015, Imagination Technologies Ltd. * Authors: Matt Redfearn (matt.redfearn@imgtec.com) */ +#include #include +#include #include #include #include #include #include +#include +#include #include #include #include +#include #define RELOCATED(x) ((void *)((long)x + offset)) @@ -165,6 +170,94 @@ static int __init relocate_exception_table(long offset) return 0; } +#ifdef CONFIG_RANDOMIZE_BASE + +static inline __init unsigned long rotate_xor(unsigned long hash, + const void *area, size_t size) +{ + size_t i; + unsigned long *ptr = (unsigned long *)area; + + for (i = 0; i < size / sizeof(hash); i++) { + /* Rotate by odd number of bits and XOR. */ + hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7); + hash ^= ptr[i]; + } + + return hash; +} + +static inline __init unsigned long get_random_boot(void) +{ + unsigned long entropy = random_get_entropy(); + unsigned long hash = 0; + + /* Attempt to create a simple but unpredictable starting entropy. */ + hash = rotate_xor(hash, linux_banner, strlen(linux_banner)); + + /* Add in any runtime entropy we can get */ + hash = rotate_xor(hash, &entropy, sizeof(entropy)); + +#if defined(CONFIG_USE_OF) + /* Get any additional entropy passed in device tree */ + { + int node, len; + u64 *prop; + + node = fdt_path_offset(initial_boot_params, "/chosen"); + if (node >= 0) { + prop = fdt_getprop_w(initial_boot_params, node, + "kaslr-seed", &len); + if (prop && (len == sizeof(u64))) + hash = rotate_xor(hash, prop, sizeof(*prop)); + } + } +#endif /* CONFIG_USE_OF */ + + return hash; +} + +static inline __init bool kaslr_disabled(void) +{ + char *str; + +#if defined(CONFIG_CMDLINE_BOOL) + const char *builtin_cmdline = CONFIG_CMDLINE; + + str = strstr(builtin_cmdline, "nokaslr"); + if (str == builtin_cmdline || + (str > builtin_cmdline && *(str - 1) == ' ')) + return true; +#endif + str = strstr(arcs_cmdline, "nokaslr"); + if (str == arcs_cmdline || (str > arcs_cmdline && *(str - 1) == ' ')) + return true; + + return false; +} + +static inline void __init *determine_relocation_address(void) +{ + /* Choose a new address for the kernel */ + unsigned long kernel_length; + void *dest = &_text; + unsigned long offset; + + if (kaslr_disabled()) + return dest; + + kernel_length = (long)_end - (long)(&_text); + + offset = get_random_boot() << 16; + offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1); + if (offset < kernel_length) + offset += ALIGN(kernel_length, 0xffff); + + return RELOCATED(dest); +} + +#else + static inline void __init *determine_relocation_address(void) { /* @@ -174,6 +267,8 @@ static inline void __init *determine_relocation_address(void) return (void *)0xffffffff81000000; } +#endif + static inline int __init relocation_addr_valid(void *loc_new) { if ((unsigned long)loc_new & 0x0000ffff) { @@ -197,6 +292,17 @@ void *__init relocate_kernel(void) /* Default to original kernel entry point */ void *kernel_entry = start_kernel; + /* Get the command line */ + fw_init_cmdline(); +#if defined(CONFIG_USE_OF) + /* Deal with the device tree */ + early_init_dt_scan(plat_get_fdt()); + if (boot_command_line[0]) { + /* Boot command line was passed in device tree */ + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + } +#endif /* CONFIG_USE_OF */ + kernel_length = (long)(&_relocation_start) - (long)(&_text); bss_length = (long)&__bss_stop - (long)&__bss_start; @@ -206,6 +312,9 @@ void *__init relocate_kernel(void) if (relocation_addr_valid(loc_new)) offset = (unsigned long)loc_new - (unsigned long)(&_text); + /* Reset the command line now so we don't end up with a duplicate */ + arcs_cmdline[0] = '\0'; + if (offset) { /* Copy the kernel to it's new location */ memcpy(loc_new, &_text, kernel_length); @@ -238,3 +347,40 @@ void *__init relocate_kernel(void) out: return kernel_entry; } + +/* + * Show relocation information on panic. + */ +void show_kernel_relocation(const char *level) +{ + unsigned long offset; + + offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS); + + if (IS_ENABLED(CONFIG_RELOCATABLE) && offset > 0) { + printk(level); + pr_cont("Kernel relocated by 0x%pK\n", (void *)offset); + pr_cont(" .text @ 0x%pK\n", _text); + pr_cont(" .data @ 0x%pK\n", _sdata); + pr_cont(" .bss @ 0x%pK\n", __bss_start); + } +} + +static int kernel_location_notifier_fn(struct notifier_block *self, + unsigned long v, void *p) +{ + show_kernel_relocation(KERN_EMERG); + return NOTIFY_DONE; +} + +static struct notifier_block kernel_location_notifier = { + .notifier_call = kernel_location_notifier_fn +}; + +static int __init register_kernel_offset_dumper(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, + &kernel_location_notifier); + return 0; +} +__initcall(register_kernel_offset_dumper); -- cgit v1.2.3-59-g8ed1b From 919beb4eedc587b70f8c1390fedac10cda783c36 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:42 +0100 Subject: MIPS: KASLR: Print relocation Information on boot When debugging a relocated kernel, the addresses of the relocated symbols and the offset applied is essential information. If the kernel is compiled with debugging information, then print this information during bootup using the same function as the panic notifier. [ralf@linux-mips.org: Fixed spelling mistake pointed out by Sergei Shtylyov .] Signed-off-by: Matt Redfearn Cc: Aaro Koskinen Cc: Masahiro Yamada Cc: Alexander Sverdlin Cc: Jaedon Shin Cc: Jonas Gorski Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12989/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 3378fdaf4dd3..9b20a0f89812 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -477,9 +477,18 @@ static void __init bootmem_init(void) */ if (__pa_symbol(_text) > __pa_symbol(VMLINUX_LOAD_ADDRESS)) { unsigned long offset; + extern void show_kernel_relocation(const char *level); offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS); free_bootmem(__pa_symbol(VMLINUX_LOAD_ADDRESS), offset); + +#if defined(CONFIG_DEBUG_KERNEL) && defined(CONFIG_DEBUG_INFO) + /* + * This information is necessary when debugging the kernel + * But is a security vulnerability otherwise! + */ + show_kernel_relocation(KERN_INFO); +#endif } #endif -- cgit v1.2.3-59-g8ed1b From 23021b2bb98543d08e22725122650644d824bf18 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Fri, 19 Feb 2016 15:42:11 -0800 Subject: MIPS: Kconfig: replace OPROFILE=n to !OPROFILE In Kconfig "=n" is not correct syntax, "!" is the preferred way for false-positive expression. Signed-off-by: Yang Shi Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12572/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 68ddb45d6258..79a1c6991c08 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2544,7 +2544,7 @@ config NODES_SHIFT config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" - depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3) + depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3) default y help Enable hardware performance counter support for perf events. If -- cgit v1.2.3-59-g8ed1b From 5c40d493e2e63d2979610aed75df7e3744b87921 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 6 Apr 2016 15:01:08 +0900 Subject: MIPS: BMIPS: Add support UART, I2C, SATA device Add UART, I2C, SATA device tree nodes on Broadcom BCM7xxx MIPS-based platforms. Signed-off-by: Jaedon Shin Reviewed-by: Florian Fainelli Cc: Kevin Cernekee Cc: Dragan Stancevic Cc: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/13016/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7125.dtsi | 69 +++++++++++++++- arch/mips/boot/dts/brcm/bcm7346.dtsi | 2 - arch/mips/boot/dts/brcm/bcm7358.dtsi | 2 - arch/mips/boot/dts/brcm/bcm7360.dtsi | 42 +++++++++- arch/mips/boot/dts/brcm/bcm7362.dtsi | 2 - arch/mips/boot/dts/brcm/bcm7420.dtsi | 77 +++++++++++++++++- arch/mips/boot/dts/brcm/bcm7425.dtsi | 94 +++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm7435.dtsi | 134 ++++++++++++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm97125cbmb.dts | 24 ++++++ arch/mips/boot/dts/brcm/bcm97360svmb.dts | 8 ++ arch/mips/boot/dts/brcm/bcm97420c.dts | 28 +++++++ arch/mips/boot/dts/brcm/bcm97425svmb.dts | 28 +++++++ arch/mips/boot/dts/brcm/bcm97435svmb.dts | 36 +++++++++ 13 files changed, 530 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm7125.dtsi b/arch/mips/boot/dts/brcm/bcm7125.dtsi index 3ae16053a0c9..550e1d9e3ee0 100644 --- a/arch/mips/boot/dts/brcm/bcm7125.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7125.dtsi @@ -85,14 +85,15 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406780 0x8>; - brcm,int-map-mask = <0x44>; + brcm,int-map-mask = <0x44>, <0xf000000>; brcm,int-fwd-mask = <0x70000>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&periph_intc>; - interrupts = <18>; + interrupts = <18>, <19>; + interrupt-names = "upg_main", "upg_bsc"; }; sun_top_ctrl: syscon@404000 { @@ -118,6 +119,70 @@ status = "disabled"; }; + uart1: serial@406b40 { + compatible = "ns16550a"; + reg = <0x406b40 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <64>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406b80 { + compatible = "ns16550a"; + reg = <0x406b80 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + bsca: i2c@406200 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406200 0x58>; + interrupts = <24>; + interrupt-names = "upg_bsca"; + status = "disabled"; + }; + + bscb: i2c@406280 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406280 0x58>; + interrupts = <25>; + interrupt-names = "upg_bscb"; + status = "disabled"; + }; + + bscc: i2c@406300 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406300 0x58>; + interrupts = <26>; + interrupt-names = "upg_bscc"; + status = "disabled"; + }; + + bscd: i2c@406380 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406380 0x58>; + interrupts = <27>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + ehci0: usb@488300 { compatible = "brcm,bcm7125-ehci", "generic-ehci"; reg = <0x488300 0x100>; diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index be7991917d29..2a6efe6942b5 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -24,8 +24,6 @@ aliases { uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; }; cpu_intc: cpu_intc { diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 060805be619a..ca57fb5eb122 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -18,8 +18,6 @@ aliases { uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; }; cpu_intc: cpu_intc { diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index bcdb09bfe07b..1c0c3d438c7a 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -18,8 +18,6 @@ aliases { uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; }; cpu_intc: cpu_intc { @@ -241,5 +239,45 @@ interrupts = <66>; status = "disabled"; }; + + sata: sata@181000 { + compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci"; + reg-names = "ahci", "top-ctrl"; + reg = <0x181000 0xa9c>, <0x180020 0x1c>; + interrupt-parent = <&periph_intc>; + interrupts = <86>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + }; + }; + + sata_phy: sata-phy@180100 { + compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3"; + reg = <0x180100 0x0eff>; + reg-names = "phy"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata_phy0: sata-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + sata_phy1: sata-phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + }; }; }; diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index d3b1b762e6c3..4153e0851b05 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -24,8 +24,6 @@ aliases { uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; }; cpu_intc: cpu_intc { diff --git a/arch/mips/boot/dts/brcm/bcm7420.dtsi b/arch/mips/boot/dts/brcm/bcm7420.dtsi index 3302a1b8a5c9..0586bf662571 100644 --- a/arch/mips/boot/dts/brcm/bcm7420.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7420.dtsi @@ -86,14 +86,15 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406780 0x8>; - brcm,int-map-mask = <0x44>; + brcm,int-map-mask = <0x44>, <0x1f000000>; brcm,int-fwd-mask = <0x70000>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&periph_intc>; - interrupts = <18>; + interrupts = <18>, <19>; + interrupt-names = "upg_main", "upg_bsc"; }; sun_top_ctrl: syscon@404000 { @@ -118,6 +119,78 @@ status = "disabled"; }; + uart1: serial@406b40 { + compatible = "ns16550a"; + reg = <0x406b40 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <64>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406b80 { + compatible = "ns16550a"; + reg = <0x406b80 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + bsca: i2c@406200 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406200 0x58>; + interrupts = <24>; + interrupt-names = "upg_bsca"; + status = "disabled"; + }; + + bscb: i2c@406280 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406280 0x58>; + interrupts = <25>; + interrupt-names = "upg_bscb"; + status = "disabled"; + }; + + bscc: i2c@406300 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406300 0x58>; + interrupts = <26>; + interrupt-names = "upg_bscc"; + status = "disabled"; + }; + + bscd: i2c@406380 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406380 0x58>; + interrupts = <27>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + + bsce: i2c@406800 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406800 0x58>; + interrupts = <28>; + interrupt-names = "upg_bsce"; + status = "disabled"; + }; + enet0: ethernet@468000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 15b27aae15a9..85339791eb2e 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -87,14 +87,32 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406780 0x8>; - brcm,int-map-mask = <0x44>; + brcm,int-map-mask = <0x44>, <0x7000000>; brcm,int-fwd-mask = <0x70000>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&periph_intc>; - interrupts = <55>; + interrupts = <55>, <53>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@409480 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x409480 0x8>; + + brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <56>, <54>, <59>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -119,6 +137,78 @@ status = "disabled"; }; + uart1: serial@406b40 { + compatible = "ns16550a"; + reg = <0x406b40 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <62>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406b80 { + compatible = "ns16550a"; + reg = <0x406b80 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <63>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + bsca: i2c@409180 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x409180 0x58>; + interrupts = <27>; + interrupt-names = "upg_bsca"; + status = "disabled"; + }; + + bscb: i2c@409400 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x409400 0x58>; + interrupts = <28>; + interrupt-names = "upg_bscb"; + status = "disabled"; + }; + + bscc: i2c@406200 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406200 0x58>; + interrupts = <24>; + interrupt-names = "upg_bscc"; + status = "disabled"; + }; + + bscd: i2c@406280 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406280 0x58>; + interrupts = <25>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + + bsce: i2c@406300 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406300 0x58>; + interrupts = <26>; + interrupt-names = "upg_bsce"; + status = "disabled"; + }; + enet0: ethernet@b80000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index a1757efe612f..cce752b27055 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -102,14 +102,32 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406780 0x8>; - brcm,int-map-mask = <0x44>; + brcm,int-map-mask = <0x44>, <0x7000000>; brcm,int-fwd-mask = <0x70000>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&periph_intc>; - interrupts = <60>; + interrupts = <60>, <58>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@409480 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x409480 0x8>; + + brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <61>, <59>, <64>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -134,6 +152,78 @@ status = "disabled"; }; + uart1: serial@406b40 { + compatible = "ns16550a"; + reg = <0x406b40 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <67>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406b80 { + compatible = "ns16550a"; + reg = <0x406b80 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <68>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + bsca: i2c@406300 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406300 0x58>; + interrupts = <26>; + interrupt-names = "upg_bsca"; + status = "disabled"; + }; + + bscb: i2c@409400 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x409400 0x58>; + interrupts = <28>; + interrupt-names = "upg_bscb"; + status = "disabled"; + }; + + bscc: i2c@406200 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406200 0x58>; + interrupts = <24>; + interrupt-names = "upg_bscc"; + status = "disabled"; + }; + + bscd: i2c@406280 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_irq0_intc>; + reg = <0x406280 0x58>; + interrupts = <25>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + + bsce: i2c@409180 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x409180 0x58>; + interrupts = <27>; + interrupt-names = "upg_bsce"; + status = "disabled"; + }; + enet0: ethernet@b80000 { phy-mode = "internal"; phy-handle = <&phy1>; @@ -236,5 +326,45 @@ interrupts = <78>; status = "disabled"; }; + + sata: sata@181000 { + compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci"; + reg-names = "ahci", "top-ctrl"; + reg = <0x181000 0xa9c>, <0x180020 0x1c>; + interrupt-parent = <&periph_intc>; + interrupts = <45>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + }; + }; + + sata_phy: sata-phy@180100 { + compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3"; + reg = <0x180100 0x0eff>; + reg-names = "phy"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata_phy0: sata-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + sata_phy1: sata-phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + }; }; }; diff --git a/arch/mips/boot/dts/brcm/bcm97125cbmb.dts b/arch/mips/boot/dts/brcm/bcm97125cbmb.dts index e046b1109eab..f2449d147c6d 100644 --- a/arch/mips/boot/dts/brcm/bcm97125cbmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97125cbmb.dts @@ -21,6 +21,30 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + /* FIXME: USB is wonky; disable it for now */ &ehci0 { status = "disabled"; diff --git a/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/arch/mips/boot/dts/brcm/bcm97360svmb.dts index d48462e091f1..73124be9548a 100644 --- a/arch/mips/boot/dts/brcm/bcm97360svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97360svmb.dts @@ -56,3 +56,11 @@ &ohci0 { status = "okay"; }; + +&sata { + status = "okay"; +}; + +&sata_phy { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97420c.dts b/arch/mips/boot/dts/brcm/bcm97420c.dts index 67fe1f3a3891..600d57abee05 100644 --- a/arch/mips/boot/dts/brcm/bcm97420c.dts +++ b/arch/mips/boot/dts/brcm/bcm97420c.dts @@ -23,6 +23,34 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + +&bsce { + status = "okay"; +}; + /* FIXME: MAC driver comes up but cannot attach to PHY */ &enet0 { status = "disabled"; diff --git a/arch/mips/boot/dts/brcm/bcm97425svmb.dts b/arch/mips/boot/dts/brcm/bcm97425svmb.dts index 689c68a4f9c8..119c714805cb 100644 --- a/arch/mips/boot/dts/brcm/bcm97425svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97425svmb.dts @@ -23,6 +23,34 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + +&bsce { + status = "okay"; +}; + &enet0 { status = "okay"; }; diff --git a/arch/mips/boot/dts/brcm/bcm97435svmb.dts b/arch/mips/boot/dts/brcm/bcm97435svmb.dts index 68f486eba3f7..43e3ba27f07b 100644 --- a/arch/mips/boot/dts/brcm/bcm97435svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97435svmb.dts @@ -23,6 +23,34 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + +&bsce { + status = "okay"; +}; + &enet0 { status = "okay"; }; @@ -58,3 +86,11 @@ &ohci3 { status = "okay"; }; + +&sata { + status = "okay"; +}; + +&sata_phy { + status = "okay"; +}; -- cgit v1.2.3-59-g8ed1b From 69ca2b81c2f63eb48eccdf70a4433641c5041527 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 6 Apr 2016 14:58:01 +0900 Subject: MIPS: BMIPS: Fix interrupt and remove needless properties Fixes wrong bcm7425 SATA AHCI hardware interrupt property value with periph_intc and SATA PHY unit address, and removes needless brcm,broken-{ncq,phy} properties what are not used anywhere. Signed-off-by: Jaedon Shin Reviewed-by: Florian Fainelli Cc: Kevin Cernekee Cc: Dragan Stancevic Cc: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/13017/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7346.dtsi | 4 +--- arch/mips/boot/dts/brcm/bcm7362.dtsi | 4 +--- arch/mips/boot/dts/brcm/bcm7425.dtsi | 6 ++---- 3 files changed, 4 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index 2a6efe6942b5..ec959061d52e 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -321,8 +321,6 @@ interrupts = <40>; #address-cells = <1>; #size-cells = <0>; - brcm,broken-ncq; - brcm,broken-phy; status = "disabled"; sata0: sata-port@0 { @@ -336,7 +334,7 @@ }; }; - sata_phy: sata-phy@1800000 { + sata_phy: sata-phy@180100 { compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3"; reg = <0x180100 0x0eff>; reg-names = "phy"; diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index 4153e0851b05..6b4713add4b8 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -244,8 +244,6 @@ interrupts = <86>; #address-cells = <1>; #size-cells = <0>; - brcm,broken-ncq; - brcm,broken-phy; status = "disabled"; sata0: sata-port@0 { @@ -259,7 +257,7 @@ }; }; - sata_phy: sata-phy@1800000 { + sata_phy: sata-phy@180100 { compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3"; reg = <0x180100 0x0eff>; reg-names = "phy"; diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 85339791eb2e..c1c15edaf829 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -317,11 +317,9 @@ reg-names = "ahci", "top-ctrl"; reg = <0x181000 0xa9c>, <0x180020 0x1c>; interrupt-parent = <&periph_intc>; - interrupts = <40>; + interrupts = <41>; #address-cells = <1>; #size-cells = <0>; - brcm,broken-ncq; - brcm,broken-phy; status = "disabled"; sata0: sata-port@0 { @@ -335,7 +333,7 @@ }; }; - sata_phy: sata-phy@1800000 { + sata_phy: sata-phy@180100 { compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3"; reg = <0x180100 0x0eff>; reg-names = "phy"; -- cgit v1.2.3-59-g8ed1b From 9ec88b60cb481a6862dc98a78400a6945d9675ba Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 6 Apr 2016 20:34:54 +0800 Subject: MIPS: Loongson1B: Some updates/fixes for LS1B - Add DMA device - Add NAND device - Add GPIO device - Add LED device - Update the defconfig and rename it to loongson1b_defconfig - Fix ioremap size - Other minor fixes Signed-off-by: Kelvin Cheung Cc: Michael Turquette Cc: Stephen Boyd Cc: Rafael J. Wysocki Cc: Viresh Kumar Cc: Vinod Koul Cc: Dan Williams Cc: Linus Walleij Cc: Alexandre Courbot Cc: Boris Brezillon Cc: Richard Weinberger Cc: David Woodhouse Cc: Brian Norris Cc: linux-mips@linux-mips.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: dmaengine@vger.kernel.org Cc: linux-gpio@vger.kernel.org Cc: linux-mtd@lists.infradead.org Patchwork: https://patchwork.linux-mips.org/patch/13033/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig | 125 ++++++++++++++++++++++ arch/mips/configs/ls1b_defconfig | 110 ------------------- arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 +++++ arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++++++ arch/mips/include/asm/mach-loongson32/platform.h | 14 ++- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 ++--- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 +++++++-------- arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +-- arch/mips/loongson32/common/platform.c | 105 +++++++++++++++++- arch/mips/loongson32/common/reset.c | 13 +-- arch/mips/loongson32/common/time.c | 27 ++--- arch/mips/loongson32/ls1b/board.c | 67 +++++++++++- 16 files changed, 440 insertions(+), 204 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 79a1c6991c08..fbd63ff8eba4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1387,6 +1387,8 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 + select ARCH_WANT_OPTIONAL_GPIOLIB + select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 release 2 instruction set. diff --git a/arch/mips/configs/loongson1b_defconfig b/arch/mips/configs/loongson1b_defconfig new file mode 100644 index 000000000000..c442f27685f4 --- /dev/null +++ b/arch/mips/configs/loongson1b_defconfig @@ -0,0 +1,125 @@ +CONFIG_MACH_LOONGSON32=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_NAMESPACES=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_LOONGSON1=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_LOONGSON1=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_HID_GENERIC=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_LOONGSON1=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_ATIME_SUPPORT=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_FTRACE is not set +# CONFIG_EARLY_PRINTK is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig deleted file mode 100644 index 1b2cc1fb26a1..000000000000 --- a/arch/mips/configs/ls1b_defconfig +++ /dev/null @@ -1,110 +0,0 @@ -CONFIG_MACH_LOONGSON32=y -CONFIG_PREEMPT=y -# CONFIG_SECCOMP is not set -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_NAMESPACES=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_EXPERT=y -CONFIG_PERF_EVENTS=y -# CONFIG_COMPAT_BRK is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_SUSPEND is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -# CONFIG_STANDALONE is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_SCSI=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -CONFIG_STMMAC_ETH=y -CONFIG_STMMAC_DA=y -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_WLAN is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_LEGACY_PTY_COUNT=8 -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set -CONFIG_USB_HID=m -CONFIG_HID_GENERIC=m -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_STORAGE=m -CONFIG_USB_SERIAL=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_LOONGSON1=y -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -# CONFIG_DNOTIFY is not set -CONFIG_VFAT_FS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_ISO8859_1=m -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_FTRACE is not set -# CONFIG_EARLY_PRINTK is not set diff --git a/arch/mips/include/asm/mach-loongson32/cpufreq.h b/arch/mips/include/asm/mach-loongson32/cpufreq.h index 6843fa1a608d..2f1ecb081223 100644 --- a/arch/mips/include/asm/mach-loongson32/cpufreq.h +++ b/arch/mips/include/asm/mach-loongson32/cpufreq.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H #define __ASM_MACH_LOONGSON32_CPUFREQ_H diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h new file mode 100644 index 000000000000..ad1dec743ccc --- /dev/null +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 Zhang, Keguang + * + * Loongson 1 NAND platform support. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_MACH_LOONGSON32_DMA_H +#define __ASM_MACH_LOONGSON32_DMA_H + +#define LS1X_DMA_CHANNEL0 0 +#define LS1X_DMA_CHANNEL1 1 +#define LS1X_DMA_CHANNEL2 2 + +struct plat_ls1x_dma { + int nr_channels; +}; + +extern struct plat_ls1x_dma ls1b_dma_pdata; + +#endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/irq.h b/arch/mips/include/asm/mach-loongson32/irq.h index 0d35b994e8d2..c1c744197de4 100644 --- a/arch/mips/include/asm/mach-loongson32/irq.h +++ b/arch/mips/include/asm/mach-loongson32/irq.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_IRQ_H #define __ASM_MACH_LOONGSON32_IRQ_H diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index 12aa129aad80..978f6df8970a 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H #define __ASM_MACH_LOONGSON32_LOONGSON1_H @@ -18,6 +17,9 @@ /* Loongson 1 Register Bases */ #define LS1X_MUX_BASE 0x1fd00420 #define LS1X_INTC_BASE 0x1fd01040 +#define LS1X_GPIO0_BASE 0x1fd010c0 +#define LS1X_GPIO1_BASE 0x1fd010c4 +#define LS1X_DMAC_BASE 0x1fd01160 #define LS1X_EHCI_BASE 0x1fe00000 #define LS1X_OHCI_BASE 0x1fe08000 #define LS1X_GMAC0_BASE 0x1fe10000 diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h new file mode 100644 index 000000000000..e274912e9de1 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Zhang, Keguang + * + * Loongson 1 NAND platform support. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_MACH_LOONGSON32_NAND_H +#define __ASM_MACH_LOONGSON32_NAND_H + +#include +#include + +struct plat_ls1x_nand { + struct mtd_partition *parts; + unsigned int nr_parts; + + int hold_cycle; + int wait_cycle; +}; + +extern struct plat_ls1x_nand ls1b_nand_pdata; + +bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); + +#endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/include/asm/mach-loongson32/platform.h b/arch/mips/include/asm/mach-loongson32/platform.h index c32f03f3f72c..672531aa9bef 100644 --- a/arch/mips/include/asm/mach-loongson32/platform.h +++ b/arch/mips/include/asm/mach-loongson32/platform.h @@ -7,20 +7,28 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_PLATFORM_H #define __ASM_MACH_LOONGSON32_PLATFORM_H #include +#include +#include + extern struct platform_device ls1x_uart_pdev; extern struct platform_device ls1x_cpufreq_pdev; +extern struct platform_device ls1x_dma_pdev; extern struct platform_device ls1x_eth0_pdev; extern struct platform_device ls1x_eth1_pdev; extern struct platform_device ls1x_ehci_pdev; +extern struct platform_device ls1x_gpio0_pdev; +extern struct platform_device ls1x_gpio1_pdev; +extern struct platform_device ls1x_nand_pdev; extern struct platform_device ls1x_rtc_pdev; -extern void __init ls1x_clk_init(void); -extern void __init ls1x_serial_setup(struct platform_device *pdev); +void __init ls1x_clk_init(void); +void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata); +void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata); +void __init ls1x_serial_set_uartclk(struct platform_device *pdev); #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-clk.h b/arch/mips/include/asm/mach-loongson32/regs-clk.h index 1f5a715ac841..4d56fc38f0c4 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-clk.h +++ b/arch/mips/include/asm/mach-loongson32/regs-clk.h @@ -19,18 +19,18 @@ #define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4) /* Clock PLL Divisor Register Bits */ -#define DIV_DC_EN (0x1 << 31) -#define DIV_DC_RST (0x1 << 30) -#define DIV_CPU_EN (0x1 << 25) -#define DIV_CPU_RST (0x1 << 24) -#define DIV_DDR_EN (0x1 << 19) -#define DIV_DDR_RST (0x1 << 18) -#define RST_DC_EN (0x1 << 5) -#define RST_DC (0x1 << 4) -#define RST_DDR_EN (0x1 << 3) -#define RST_DDR (0x1 << 2) -#define RST_CPU_EN (0x1 << 1) -#define RST_CPU 0x1 +#define DIV_DC_EN BIT(31) +#define DIV_DC_RST BIT(30) +#define DIV_CPU_EN BIT(25) +#define DIV_CPU_RST BIT(24) +#define DIV_DDR_EN BIT(19) +#define DIV_DDR_RST BIT(18) +#define RST_DC_EN BIT(5) +#define RST_DC BIT(4) +#define RST_DDR_EN BIT(3) +#define RST_DDR BIT(2) +#define RST_CPU_EN BIT(1) +#define RST_CPU BIT(0) #define DIV_DC_SHIFT 26 #define DIV_CPU_SHIFT 20 diff --git a/arch/mips/include/asm/mach-loongson32/regs-mux.h b/arch/mips/include/asm/mach-loongson32/regs-mux.h index 8302d92f2da2..7c394f93cb9e 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-mux.h +++ b/arch/mips/include/asm/mach-loongson32/regs-mux.h @@ -19,49 +19,49 @@ #define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4) /* MUX CTRL0 Register Bits */ -#define UART0_USE_PWM23 (0x1 << 28) -#define UART0_USE_PWM01 (0x1 << 27) -#define UART1_USE_LCD0_5_6_11 (0x1 << 26) -#define I2C2_USE_CAN1 (0x1 << 25) -#define I2C1_USE_CAN0 (0x1 << 24) -#define NAND3_USE_UART5 (0x1 << 23) -#define NAND3_USE_UART4 (0x1 << 22) -#define NAND3_USE_UART1_DAT (0x1 << 21) -#define NAND3_USE_UART1_CTS (0x1 << 20) -#define NAND3_USE_PWM23 (0x1 << 19) -#define NAND3_USE_PWM01 (0x1 << 18) -#define NAND2_USE_UART5 (0x1 << 17) -#define NAND2_USE_UART4 (0x1 << 16) -#define NAND2_USE_UART1_DAT (0x1 << 15) -#define NAND2_USE_UART1_CTS (0x1 << 14) -#define NAND2_USE_PWM23 (0x1 << 13) -#define NAND2_USE_PWM01 (0x1 << 12) -#define NAND1_USE_UART5 (0x1 << 11) -#define NAND1_USE_UART4 (0x1 << 10) -#define NAND1_USE_UART1_DAT (0x1 << 9) -#define NAND1_USE_UART1_CTS (0x1 << 8) -#define NAND1_USE_PWM23 (0x1 << 7) -#define NAND1_USE_PWM01 (0x1 << 6) -#define GMAC1_USE_UART1 (0x1 << 4) -#define GMAC1_USE_UART0 (0x1 << 3) -#define LCD_USE_UART0_DAT (0x1 << 2) -#define LCD_USE_UART15 (0x1 << 1) -#define LCD_USE_UART0 0x1 +#define UART0_USE_PWM23 BIT(28) +#define UART0_USE_PWM01 BIT(27) +#define UART1_USE_LCD0_5_6_11 BIT(26) +#define I2C2_USE_CAN1 BIT(25) +#define I2C1_USE_CAN0 BIT(24) +#define NAND3_USE_UART5 BIT(23) +#define NAND3_USE_UART4 BIT(22) +#define NAND3_USE_UART1_DAT BIT(21) +#define NAND3_USE_UART1_CTS BIT(20) +#define NAND3_USE_PWM23 BIT(19) +#define NAND3_USE_PWM01 BIT(18) +#define NAND2_USE_UART5 BIT(17) +#define NAND2_USE_UART4 BIT(16) +#define NAND2_USE_UART1_DAT BIT(15) +#define NAND2_USE_UART1_CTS BIT(14) +#define NAND2_USE_PWM23 BIT(13) +#define NAND2_USE_PWM01 BIT(12) +#define NAND1_USE_UART5 BIT(11) +#define NAND1_USE_UART4 BIT(10) +#define NAND1_USE_UART1_DAT BIT(9) +#define NAND1_USE_UART1_CTS BIT(8) +#define NAND1_USE_PWM23 BIT(7) +#define NAND1_USE_PWM01 BIT(6) +#define GMAC1_USE_UART1 BIT(4) +#define GMAC1_USE_UART0 BIT(3) +#define LCD_USE_UART0_DAT BIT(2) +#define LCD_USE_UART15 BIT(1) +#define LCD_USE_UART0 BIT(0) /* MUX CTRL1 Register Bits */ -#define USB_RESET (0x1 << 31) -#define SPI1_CS_USE_PWM01 (0x1 << 24) -#define SPI1_USE_CAN (0x1 << 23) -#define DISABLE_DDR_CONFSPACE (0x1 << 20) -#define DDR32TO16EN (0x1 << 16) -#define GMAC1_SHUT (0x1 << 13) -#define GMAC0_SHUT (0x1 << 12) -#define USB_SHUT (0x1 << 11) -#define UART1_3_USE_CAN1 (0x1 << 5) -#define UART1_2_USE_CAN0 (0x1 << 4) -#define GMAC1_USE_TXCLK (0x1 << 3) -#define GMAC0_USE_TXCLK (0x1 << 2) -#define GMAC1_USE_PWM23 (0x1 << 1) -#define GMAC0_USE_PWM01 0x1 +#define USB_RESET BIT(31) +#define SPI1_CS_USE_PWM01 BIT(24) +#define SPI1_USE_CAN BIT(23) +#define DISABLE_DDR_CONFSPACE BIT(20) +#define DDR32TO16EN BIT(16) +#define GMAC1_SHUT BIT(13) +#define GMAC0_SHUT BIT(12) +#define USB_SHUT BIT(11) +#define UART1_3_USE_CAN1 BIT(5) +#define UART1_2_USE_CAN0 BIT(4) +#define GMAC1_USE_TXCLK BIT(3) +#define GMAC0_USE_TXCLK BIT(2) +#define GMAC1_USE_PWM23 BIT(1) +#define GMAC0_USE_PWM01 BIT(0) #endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h b/arch/mips/include/asm/mach-loongson32/regs-pwm.h index 69f174ed13a4..4119600ce79a 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h +++ b/arch/mips/include/asm/mach-loongson32/regs-pwm.h @@ -19,11 +19,11 @@ #define PWM_CTRL 0xc /* PWM Control Register Bits */ -#define CNT_RST (0x1 << 7) -#define INT_SR (0x1 << 6) -#define INT_EN (0x1 << 5) -#define PWM_SINGLE (0x1 << 4) -#define PWM_OE (0x1 << 3) -#define CNT_EN 0x1 +#define CNT_RST BIT(7) +#define INT_SR BIT(6) +#define INT_EN BIT(5) +#define PWM_SINGLE BIT(4) +#define PWM_OE BIT(3) +#define CNT_EN BIT(0) #endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */ diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c index ddf1d4cbf31e..f2c714d8fb60 100644 --- a/arch/mips/loongson32/common/platform.c +++ b/arch/mips/loongson32/common/platform.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Zhang, Keguang + * Copyright (c) 2011-2016 Zhang, Keguang * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -10,14 +10,17 @@ #include #include #include +#include +#include #include #include #include #include -#include -#include #include +#include +#include +#include /* 8250/16550 compatible UART */ #define LS1X_UART(_id) \ @@ -45,7 +48,7 @@ struct platform_device ls1x_uart_pdev = { }, }; -void __init ls1x_serial_setup(struct platform_device *pdev) +void __init ls1x_serial_set_uartclk(struct platform_device *pdev) { struct clk *clk; struct plat_serial8250_port *p; @@ -77,6 +80,42 @@ struct platform_device ls1x_cpufreq_pdev = { }, }; +/* DMA */ +static struct resource ls1x_dma_resources[] = { + [0] = { + .start = LS1X_DMAC_BASE, + .end = LS1X_DMAC_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = LS1X_DMA0_IRQ, + .end = LS1X_DMA0_IRQ, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = LS1X_DMA1_IRQ, + .end = LS1X_DMA1_IRQ, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = LS1X_DMA2_IRQ, + .end = LS1X_DMA2_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device ls1x_dma_pdev = { + .name = "ls1x-dma", + .id = -1, + .num_resources = ARRAY_SIZE(ls1x_dma_resources), + .resource = ls1x_dma_resources, +}; + +void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata) +{ + ls1x_dma_pdev.dev.platform_data = pdata; +} + /* Synopsys Ethernet GMAC */ static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { .phy_mask = 0, @@ -198,6 +237,64 @@ struct platform_device ls1x_eth1_pdev = { }, }; +/* GPIO */ +static struct resource ls1x_gpio0_resources[] = { + [0] = { + .start = LS1X_GPIO0_BASE, + .end = LS1X_GPIO0_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device ls1x_gpio0_pdev = { + .name = "ls1x-gpio", + .id = 0, + .num_resources = ARRAY_SIZE(ls1x_gpio0_resources), + .resource = ls1x_gpio0_resources, +}; + +static struct resource ls1x_gpio1_resources[] = { + [0] = { + .start = LS1X_GPIO1_BASE, + .end = LS1X_GPIO1_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device ls1x_gpio1_pdev = { + .name = "ls1x-gpio", + .id = 1, + .num_resources = ARRAY_SIZE(ls1x_gpio1_resources), + .resource = ls1x_gpio1_resources, +}; + +/* NAND Flash */ +static struct resource ls1x_nand_resources[] = { + [0] = { + .start = LS1X_NAND_BASE, + .end = LS1X_NAND_BASE + SZ_32 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMA channel 0 is dedicated to NAND */ + .start = LS1X_DMA_CHANNEL0, + .end = LS1X_DMA_CHANNEL0, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device ls1x_nand_pdev = { + .name = "ls1x-nand", + .id = -1, + .num_resources = ARRAY_SIZE(ls1x_nand_resources), + .resource = ls1x_nand_resources, +}; + +void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata) +{ + ls1x_nand_pdev.dev.platform_data = pdata; +} + /* USB EHCI */ static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); diff --git a/arch/mips/loongson32/common/reset.c b/arch/mips/loongson32/common/reset.c index c41e4ca56ab4..8a1d9cc5a134 100644 --- a/arch/mips/loongson32/common/reset.c +++ b/arch/mips/loongson32/common/reset.c @@ -9,12 +9,13 @@ #include #include +#include #include #include #include -static void __iomem *wdt_base; +static void __iomem *wdt_reg_base; static void ls1x_halt(void) { @@ -26,9 +27,9 @@ static void ls1x_halt(void) static void ls1x_restart(char *command) { - __raw_writel(0x1, wdt_base + WDT_EN); - __raw_writel(0x1, wdt_base + WDT_TIMER); - __raw_writel(0x1, wdt_base + WDT_SET); + __raw_writel(0x1, wdt_reg_base + WDT_EN); + __raw_writel(0x1, wdt_reg_base + WDT_TIMER); + __raw_writel(0x1, wdt_reg_base + WDT_SET); ls1x_halt(); } @@ -40,8 +41,8 @@ static void ls1x_power_off(void) static int __init ls1x_reboot_setup(void) { - wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f); - if (!wdt_base) + wdt_reg_base = ioremap_nocache(LS1X_WDT_BASE, (SZ_4 + SZ_8)); + if (!wdt_reg_base) panic("Failed to remap watchdog registers"); _machine_restart = ls1x_restart; diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index 0996b025eeef..ff224f0020e5 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -35,25 +36,25 @@ DEFINE_RAW_SPINLOCK(ls1x_timer_lock); -static void __iomem *timer_base; +static void __iomem *timer_reg_base; static uint32_t ls1x_jiffies_per_tick; static inline void ls1x_pwmtimer_set_period(uint32_t period) { - __raw_writel(period, timer_base + PWM_HRC); - __raw_writel(period, timer_base + PWM_LRC); + __raw_writel(period, timer_reg_base + PWM_HRC); + __raw_writel(period, timer_reg_base + PWM_LRC); } static inline void ls1x_pwmtimer_restart(void) { - __raw_writel(0x0, timer_base + PWM_CNT); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(0x0, timer_reg_base + PWM_CNT); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); } void __init ls1x_pwmtimer_init(void) { - timer_base = ioremap(LS1X_TIMER_BASE, 0xf); - if (!timer_base) + timer_reg_base = ioremap_nocache(LS1X_TIMER_BASE, SZ_16); + if (!timer_reg_base) panic("Failed to remap timer registers"); ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); @@ -86,7 +87,7 @@ static cycle_t ls1x_clocksource_read(struct clocksource *cs) */ jifs = jiffies; /* read the count */ - count = __raw_readl(timer_base + PWM_CNT); + count = __raw_readl(timer_reg_base + PWM_CNT); /* * It's possible for count to appear to go the wrong way for this @@ -131,7 +132,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) raw_spin_lock(&ls1x_timer_lock); ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); ls1x_pwmtimer_restart(); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -140,7 +141,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) { raw_spin_lock(&ls1x_timer_lock); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -149,8 +150,8 @@ static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd) { raw_spin_lock(&ls1x_timer_lock); - __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN, - timer_base + PWM_CTRL); + __raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN, + timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -220,7 +221,7 @@ void __init plat_time_init(void) #ifdef CONFIG_CEVT_CSRC_LS1X /* setup LS1X PWM timer */ - clk = clk_get(NULL, "ls1x_pwmtimer"); + clk = clk_get(NULL, "ls1x-pwmtimer"); if (IS_ERR(clk)) panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 58daeea25739..38a1d404be1b 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Zhang, Keguang + * Copyright (c) 2011-2016 Zhang, Keguang * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -7,26 +7,83 @@ * option) any later version. */ +#include +#include +#include + +#include +#include +#include #include +struct plat_ls1x_dma ls1x_dma_pdata = { + .nr_channels = 3, +}; + +static struct mtd_partition ls1x_nand_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = SZ_16M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +struct plat_ls1x_nand ls1x_nand_pdata = { + .parts = ls1x_nand_parts, + .nr_parts = ARRAY_SIZE(ls1x_nand_parts), + .hold_cycle = 0x2, + .wait_cycle = 0xc, +}; + +static const struct gpio_led ls1x_gpio_leds[] __initconst = { + { + .name = "LED9", + .default_trigger = "heartbeat", + .gpio = 38, + .active_low = 1, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, { + .name = "LED6", + .default_trigger = "nand-disk", + .gpio = 39, + .active_low = 1, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, +}; + +static const struct gpio_led_platform_data ls1x_led_pdata __initconst = { + .num_leds = ARRAY_SIZE(ls1x_gpio_leds), + .leds = ls1x_gpio_leds, +}; + static struct platform_device *ls1b_platform_devices[] __initdata = { &ls1x_uart_pdev, &ls1x_cpufreq_pdev, + &ls1x_dma_pdev, &ls1x_eth0_pdev, &ls1x_eth1_pdev, &ls1x_ehci_pdev, + &ls1x_gpio0_pdev, + &ls1x_gpio1_pdev, + &ls1x_nand_pdev, &ls1x_rtc_pdev, }; static int __init ls1b_platform_init(void) { - int err; + ls1x_serial_set_uartclk(&ls1x_uart_pdev); + ls1x_dma_set_platdata(&ls1x_dma_pdata); + ls1x_nand_set_platdata(&ls1x_nand_pdata); - ls1x_serial_setup(&ls1x_uart_pdev); + gpio_led_register_device(-1, &ls1x_led_pdata); - err = platform_add_devices(ls1b_platform_devices, + return platform_add_devices(ls1b_platform_devices, ARRAY_SIZE(ls1b_platform_devices)); - return err; } arch_initcall(ls1b_platform_init); -- cgit v1.2.3-59-g8ed1b From eb1472e7df2c0e1f1c3e207630ffdd008e98f271 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Jan 2016 12:13:15 -0800 Subject: MIPS: BCM63xx: Enable partition parser in defconfig Enable CONFIG_MTD_BCM63XX_PARTS in arch/mips/configs/bcm63xx_defconfig since this is a necessary option to parse the built-in flash partition table on BCM63xx SoCs. Signed-off-by: Florian Fainelli Acked-by: Brian Norris Cc: cernekee@gmail.com Cc: jogo@openwrt.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12255/ Signed-off-by: Ralf Baechle --- arch/mips/configs/bcm63xx_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/configs/bcm63xx_defconfig b/arch/mips/configs/bcm63xx_defconfig index 3fec26410f34..5599a9f1e3c6 100644 --- a/arch/mips/configs/bcm63xx_defconfig +++ b/arch/mips/configs/bcm63xx_defconfig @@ -44,6 +44,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_MTD=y +CONFIG_MTD_BCM63XX_PARTS=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -- cgit v1.2.3-59-g8ed1b From 0201bfb1af4747f3642fa7a707fd81bbf78390b7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Jan 2016 12:13:16 -0800 Subject: MIPS: BMIPS: Enable partition parser in defconfig Enable CONFIG_MTD_BCM63XX_PARTS in arch/mips/configs/bmips_be_defconfig since this is a necessary option to parse the built-in flash partition table on BMIPS big-endian SoCs (Cable Modem and DSL). Signed-off-by: Florian Fainelli Acked-by: Brian Norris Cc: cernekee@gmail.com Cc: jogo@openwrt.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12256/ Signed-off-by: Ralf Baechle --- arch/mips/configs/bmips_be_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/configs/bmips_be_defconfig b/arch/mips/configs/bmips_be_defconfig index 24dcb90b0f64..acf7785c4cdb 100644 --- a/arch/mips/configs/bmips_be_defconfig +++ b/arch/mips/configs/bmips_be_defconfig @@ -36,6 +36,7 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_PRINTK_TIME=y CONFIG_BRCMSTB_GISB_ARB=y CONFIG_MTD=y +CONFIG_MTD_BCM63XX_PARTS=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -- cgit v1.2.3-59-g8ed1b From c130d2fd3d59fbd5d269f7d5827bd4ed1d94aec6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:34 -0700 Subject: MIPS: BMIPS: BMIPS5000 has I cache filing from D cache BMIPS5000 and BMIPS52000 processors have their I-cache filling from the D-cache. Since BMIPS_GENERIC does not provide (yet) a cpu-feature-overrides.h file, this was not set anywhere, so make sure the R4K cache detection takes care of that. Fixes: d74b0172e4e2c ("MIPS: BMIPS: Add special cache handling in c-r4k.c") Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13010/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index e64d595fdcf2..92e54fbdbf96 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1317,6 +1317,10 @@ static void probe_pcache(void) c->icache.flags |= MIPS_CACHE_IC_F_DC; break; + case CPU_BMIPS5000: + c->icache.flags |= MIPS_CACHE_IC_F_DC; + break; + case CPU_LOONGSON2: /* * LOONGSON2 has 4 way icache, but when using indexed cache op, -- cgit v1.2.3-59-g8ed1b From 73c4ca047f440c79f545bc6133e3033f754cd239 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:35 -0700 Subject: MIPS: BMIPS: Clear MIPS_CACHE_ALIASES earlier BMIPS5000 and BMIPS5200 processor have no D cache aliases, and this is properly handled by the per-CPU override added at the end of r4k_cache_init(), the problem is that the output of probe_pcache() disagrees with that, since this is too late: Primary instruction cache 32kB, VIPT, 4-way, linesize 64 bytes. Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes With the change moved earlier, we now have a consistent output with the settings we are intending to have: Primary instruction cache 32kB, VIPT, 4-way, linesize 64 bytes. Primary data cache 32kB, 4-way, VIPT, no aliases, linesize 32 bytes Fixes: d74b0172e4e2c ("MIPS: BMIPS: Add special cache handling in c-r4k.c") Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13011/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 92e54fbdbf96..226516d9c851 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1319,6 +1319,8 @@ static void probe_pcache(void) case CPU_BMIPS5000: c->icache.flags |= MIPS_CACHE_IC_F_DC; + /* Cache aliases are handled in hardware; allow HIGHMEM */ + c->dcache.flags &= ~MIPS_CACHE_ALIASES; break; case CPU_LOONGSON2: @@ -1758,8 +1760,6 @@ void r4k_cache_init(void) flush_icache_range = (void *)b5k_instruction_hazard; local_flush_icache_range = (void *)b5k_instruction_hazard; - /* Cache aliases are handled in hardware; allow HIGHMEM */ - current_cpu_data.dcache.flags &= ~MIPS_CACHE_ALIASES; /* Optimization: an L2 flush implicitly flushes the L1 */ current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES; -- cgit v1.2.3-59-g8ed1b From f675843ddfdfdf467d08cc922201614a149e439e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:36 -0700 Subject: MIPS: BMIPS: local_r4k___flush_cache_all needs to blast S-cache local_r4k___flush_cache_all() is missing a special check for BMIPS5000 processors, we need to blast the S-cache, just like other MTI processors since we have an inclusive cache. We also need an additional __sync() to make sure this is completed. Fixes: d74b0172e4e2c ("MIPS: BMIPS: Add special cache handling in c-r4k.c") Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13012/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 226516d9c851..6f43bdf9a679 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -447,6 +447,11 @@ static inline void local_r4k___flush_cache_all(void * args) r4k_blast_scache(); break; + case CPU_BMIPS5000: + r4k_blast_scache(); + __sync(); + break; + default: r4k_blast_dcache(); r4k_blast_icache(); -- cgit v1.2.3-59-g8ed1b From f337967d6d87da39f6e59d90430f3bec0909edf5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:37 -0700 Subject: MIPS: BMIPS: Add cpu-feature-overrides.h BMIPS_GENERIC being multiplatform and intended to support BMIPS3200, BMIPS3300, BMIPS4350, BMIPS4380 and BMIPS5000-class processors, there is not much more we can put in there since they do not share the same I and D cache line sizes at all (doubled for every new generation essentially), some processors have a S-cache, some don't, some have a FPU, some don't. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13013/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h (limited to 'arch') diff --git a/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h new file mode 100644 index 000000000000..fa0583e1ce0d --- /dev/null +++ b/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h @@ -0,0 +1,14 @@ +#ifndef __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H + +/* Invariants across all BMIPS processors */ +#define cpu_has_vtag_icache 0 +#define cpu_icache_snoops_remote_store 1 + +/* Processor ISA compatibility is MIPS32R1 */ +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H */ -- cgit v1.2.3-59-g8ed1b From 37808d62afcdc420d98875c4b514c178d56f6815 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:38 -0700 Subject: MIPS: BMIPS: Pretty print BMIPS5200 processor name Just to ease debugging of multiplatform kernel, make sure we print "Broadcom BMIPS5200" for the BMIPS5200 implementation instead of Broadcom BMIPS5000. Fixes: 68e6a78373a6d ("MIPS: BMIPS: Add PRId for BMIPS5200 (Whirlwind)") Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13014/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index d0818aab00e2..d72bd7eb8bce 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1459,7 +1459,10 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) case PRID_IMP_BMIPS5000: case PRID_IMP_BMIPS5200: c->cputype = CPU_BMIPS5000; - __cpu_name[cpu] = "Broadcom BMIPS5000"; + if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200) + __cpu_name[cpu] = "Broadcom BMIPS5200"; + else + __cpu_name[cpu] = "Broadcom BMIPS5000"; set_elf_platform(cpu, "bmips5000"); c->options |= MIPS_CPU_ULRI; break; -- cgit v1.2.3-59-g8ed1b From 3604b4510c17c16271b3446528807227dfb02b04 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:56:47 +0200 Subject: MIPS: BMIPS: Add BCM6358 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6358 has a shared TLB which conflicts with current SMP support, so it must be disabled for now. BCM6358 uses >= 0xfffe0000 addresses for internal registers, which need to be remapped (by using a simplified version of BRCM63xx ioremap.h). However, 0xfff80000 is a better address, since it also covers BCM3368, leaving the possibility to add it in the future. Signed-off-by: Álvaro Fernández Rojas Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13040/ Signed-off-by: Ralf Baechle --- arch/mips/bmips/setup.c | 10 +++++++++ arch/mips/include/asm/mach-bmips/ioremap.h | 33 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 arch/mips/include/asm/mach-bmips/ioremap.h (limited to 'arch') diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index b764995343c1..c63bc0af61fc 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -95,6 +95,15 @@ static void bcm6328_quirks(void) bcm63xx_fixup_cpu1(); } +static void bcm6358_quirks(void) +{ + /* + * BCM6358 needs special handling for its shared TLB, so + * disable SMP for now + */ + bmips_smp_enabled = 0; +} + static void bcm6368_quirks(void) { bcm63xx_fixup_cpu1(); @@ -104,6 +113,7 @@ static const struct bmips_quirk bmips_quirk_list[] = { { "brcm,bcm3384-viper", &bcm3384_viper_quirks }, { "brcm,bcm33843-viper", &bcm3384_viper_quirks }, { "brcm,bcm6328", &bcm6328_quirks }, + { "brcm,bcm6358", &bcm6358_quirks }, { "brcm,bcm6368", &bcm6368_quirks }, { "brcm,bcm63168", &bcm6368_quirks }, { }, diff --git a/arch/mips/include/asm/mach-bmips/ioremap.h b/arch/mips/include/asm/mach-bmips/ioremap.h new file mode 100644 index 000000000000..29c7a7bb7080 --- /dev/null +++ b/arch/mips/include/asm/mach-bmips/ioremap.h @@ -0,0 +1,33 @@ +#ifndef __ASM_MACH_BMIPS_IOREMAP_H +#define __ASM_MACH_BMIPS_IOREMAP_H + +#include + +static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) +{ + return phys_addr; +} + +static inline int is_bmips_internal_registers(phys_addr_t offset) +{ + if (offset >= 0xfff80000) + return 1; + + return 0; +} + +static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, + unsigned long flags) +{ + if (is_bmips_internal_registers(offset)) + return (void __iomem *)offset; + + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return is_bmips_internal_registers((unsigned long)addr); +} + +#endif /* __ASM_MACH_BMIPS_IOREMAP_H */ -- cgit v1.2.3-59-g8ed1b From 7537d273e2f3c95c17f6a2c8662209f5d18dbbbc Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:56:48 +0200 Subject: MIPS: BMIPS: Add device tree example for BCM6358 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a device tree example for SFR Neufbox4 (Sercomm version), which also serves as a real example for brcm,bcm6358-leds. Signed-off-by: Álvaro Fernández Rojas Acked-by: Rob Herring Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13041/ Signed-off-by: Ralf Baechle --- .../devicetree/bindings/mips/brcm/soc.txt | 2 +- arch/mips/bmips/Kconfig | 4 + arch/mips/boot/dts/brcm/Makefile | 2 + arch/mips/boot/dts/brcm/bcm6358.dtsi | 130 +++++++++++++++++++++ arch/mips/boot/dts/brcm/bcm96358nb4ser.dts | 46 ++++++++ 5 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 arch/mips/boot/dts/brcm/bcm6358.dtsi create mode 100644 arch/mips/boot/dts/brcm/bcm96358nb4ser.dts (limited to 'arch') diff --git a/Documentation/devicetree/bindings/mips/brcm/soc.txt b/Documentation/devicetree/bindings/mips/brcm/soc.txt index 7bab90cc4a7b..e58a4f6d1360 100644 --- a/Documentation/devicetree/bindings/mips/brcm/soc.txt +++ b/Documentation/devicetree/bindings/mips/brcm/soc.txt @@ -4,7 +4,7 @@ Required properties: - compatible: "brcm,bcm3384", "brcm,bcm33843" "brcm,bcm3384-viper", "brcm,bcm33843-viper" - "brcm,bcm6328", "brcm,bcm6368", + "brcm,bcm6328", "brcm,bcm6358", "brcm,bcm6368", "brcm,bcm7125", "brcm,bcm7346", "brcm,bcm7358", "brcm,bcm7360", "brcm,bcm7362", "brcm,bcm7420", "brcm,bcm7425" diff --git a/arch/mips/bmips/Kconfig b/arch/mips/bmips/Kconfig index e2c4fd682c74..264328d528c7 100644 --- a/arch/mips/bmips/Kconfig +++ b/arch/mips/bmips/Kconfig @@ -21,6 +21,10 @@ config DT_BCM93384WVG_VIPER bool "BCM93384WVG Viper CPU (EXPERIMENTAL)" select BUILTIN_DTB +config DT_BCM96358NB4SER + bool "BCM96358NB4SER" + select BUILTIN_DTB + config DT_BCM96368MVWG bool "BCM96368MVWG" select BUILTIN_DTB diff --git a/arch/mips/boot/dts/brcm/Makefile b/arch/mips/boot/dts/brcm/Makefile index eabeb603e805..fda9d387cc08 100644 --- a/arch/mips/boot/dts/brcm/Makefile +++ b/arch/mips/boot/dts/brcm/Makefile @@ -1,5 +1,6 @@ dtb-$(CONFIG_DT_BCM93384WVG) += bcm93384wvg.dtb dtb-$(CONFIG_DT_BCM93384WVG_VIPER) += bcm93384wvg_viper.dtb +dtb-$(CONFIG_DT_BCM96358NB4SER) += bcm96358nb4ser.dtb dtb-$(CONFIG_DT_BCM96368MVWG) += bcm96368mvwg.dtb dtb-$(CONFIG_DT_BCM9EJTAGPRB) += bcm9ejtagprb.dtb dtb-$(CONFIG_DT_BCM97125CBMB) += bcm97125cbmb.dtb @@ -14,6 +15,7 @@ dtb-$(CONFIG_DT_BCM97435SVMB) += bcm97435svmb.dtb dtb-$(CONFIG_DT_NONE) += \ bcm93384wvg.dtb \ bcm93384wvg_viper.dtb \ + bcm96358nb4ser.dtb \ bcm96368mvwg.dtb \ bcm9ejtagprb.dtb \ bcm97125cbmb.dtb \ diff --git a/arch/mips/boot/dts/brcm/bcm6358.dtsi b/arch/mips/boot/dts/brcm/bcm6358.dtsi new file mode 100644 index 000000000000..f9d8d392162b --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm6358.dtsi @@ -0,0 +1,130 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm6358"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <150000000>; + + cpu@0 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <1>; + }; + }; + + clocks { + periph_clk: periph-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + }; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + cpu_intc: interrupt-controller { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + ubus { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges; + + periph_cntl: syscon@fffe0000 { + compatible = "syscon"; + reg = <0xfffe0000 0xc>; + native-endian; + }; + + reboot: syscon-reboot@fffe0008 { + compatible = "syscon-reboot"; + regmap = <&periph_cntl>; + offset = <0x8>; + mask = <0x1>; + }; + + periph_intc: interrupt-controller@fffe000c { + compatible = "brcm,bcm6345-l1-intc"; + reg = <0xfffe000c 0x8>, + <0xfffe0038 0x8>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + leds0: led-controller@fffe00d0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,bcm6358-leds"; + reg = <0xfffe00d0 0x8>; + + status = "disabled"; + }; + + uart0: serial@fffe0100 { + compatible = "brcm,bcm6345-uart"; + reg = <0xfffe0100 0x18>; + + interrupt-parent = <&periph_intc>; + interrupts = <2>; + + clocks = <&periph_clk>; + + status = "disabled"; + }; + + uart1: serial@fffe0120 { + compatible = "brcm,bcm6345-uart"; + reg = <0xfffe0120 0x18>; + + interrupt-parent = <&periph_intc>; + interrupts = <3>; + + clocks = <&periph_clk>; + + status = "disabled"; + }; + + ehci: usb@fffe1300 { + compatible = "brcm,bcm6358-ehci", "generic-ehci"; + reg = <0xfffe1300 0x100>; + big-endian; + interrupt-parent = <&periph_intc>; + interrupts = <10>; + status = "disabled"; + }; + + ohci: usb@fffe1400 { + compatible = "brcm,bcm6358-ohci", "generic-ohci"; + reg = <0xfffe1400 0x100>; + big-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <5>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts b/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts new file mode 100644 index 000000000000..f412117972e6 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts @@ -0,0 +1,46 @@ +/dts-v1/; + +/include/ "bcm6358.dtsi" + +/ { + compatible = "sfr,nb4-ser", "brcm,bcm6358"; + model = "SFR Neufbox 4 (Sercomm)"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x02000000>; + }; + + chosen { + stdout-path = &uart0; + }; +}; + +&leds0 { + status = "ok"; + + led@0 { + reg = <0>; + active-low; + label = "nb4-ser:white:alarm"; + }; + led@2 { + reg = <2>; + active-low; + label = "nb4-ser:white:tv"; + }; + led@3 { + reg = <3>; + active-low; + label = "nb4-ser:white:tel"; + }; + led@4 { + reg = <4>; + active-low; + label = "nb4-ser:white:adsl"; + }; +}; + +&uart0 { + status = "okay"; +}; -- cgit v1.2.3-59-g8ed1b From 3652acd2315562614826eba7d38fae51389636f9 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:57:19 +0200 Subject: MIPS: BMIPS: Add support for BCM63268 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This SoC is very similar to BCM63168 and Broadcom usually refers to them as BCM63268. Add BCM63268 and missing BCM63168 to device tree documentation. Signed-off-by: Álvaro Fernández Rojas Acked-by: Rob Herring Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13042/ Signed-off-by: Ralf Baechle --- Documentation/devicetree/bindings/mips/brcm/soc.txt | 1 + arch/mips/bmips/setup.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/Documentation/devicetree/bindings/mips/brcm/soc.txt b/Documentation/devicetree/bindings/mips/brcm/soc.txt index e58a4f6d1360..4a7e030e4f9b 100644 --- a/Documentation/devicetree/bindings/mips/brcm/soc.txt +++ b/Documentation/devicetree/bindings/mips/brcm/soc.txt @@ -5,6 +5,7 @@ Required properties: - compatible: "brcm,bcm3384", "brcm,bcm33843" "brcm,bcm3384-viper", "brcm,bcm33843-viper" "brcm,bcm6328", "brcm,bcm6358", "brcm,bcm6368", + "brcm,bcm63168", "brcm,bcm63268", "brcm,bcm7125", "brcm,bcm7346", "brcm,bcm7358", "brcm,bcm7360", "brcm,bcm7362", "brcm,bcm7420", "brcm,bcm7425" diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index c63bc0af61fc..f146d1219bde 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -116,6 +116,7 @@ static const struct bmips_quirk bmips_quirk_list[] = { { "brcm,bcm6358", &bcm6358_quirks }, { "brcm,bcm6368", &bcm6368_quirks }, { "brcm,bcm63168", &bcm6368_quirks }, + { "brcm,bcm63268", &bcm6368_quirks }, { }, }; -- cgit v1.2.3-59-g8ed1b From e3b992d028f828621fa2441b445478fd86651cad Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:57:48 +0200 Subject: MIPS: BMIPS: Improve BCM6328 device tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unneeded leds0 alias. - Switch to bcm6345-l1-intc interrupt controller. - Use interrupt-controller instead of periph_intc and cpu_intc. - Add uart1, ehci and ohci nodes. - Refactor syscon and syscon-reboot. - Avoid using underscores in node names. - Rename uart aliases to serial. Signed-off-by: Álvaro Fernández Rojas Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13043/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm6328.dtsi | 50 ++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi index 9d19236f53e7..5633b9d90f55 100644 --- a/arch/mips/boot/dts/brcm/bcm6328.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi @@ -23,7 +23,7 @@ }; clocks { - periph_clk: periph_clk { + periph_clk: periph-clk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <50000000>; @@ -31,11 +31,11 @@ }; aliases { - leds0 = &leds0; - uart0 = &uart0; + serial0 = &uart0; + serial1 = &uart1; }; - cpu_intc: cpu_intc { + cpu_intc: interrupt-controller { #address-cells = <0>; compatible = "mti,cpu-interrupt-controller"; @@ -50,16 +50,16 @@ compatible = "simple-bus"; ranges; - periph_intc: periph_intc@10000020 { - compatible = "brcm,bcm3380-l2-intc"; - reg = <0x10000024 0x4 0x1000002c 0x4>, - <0x10000020 0x4 0x10000028 0x4>; + periph_intc: interrupt-controller@10000020 { + compatible = "brcm,bcm6345-l1-intc"; + reg = <0x10000020 0x10>, + <0x10000030 0x10>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&cpu_intc>; - interrupts = <2>; + interrupts = <2>, <3>; }; uart0: serial@10000100 { @@ -71,13 +71,22 @@ status = "disabled"; }; - timer: timer@10000040 { + uart1: serial@10000120 { + compatible = "brcm,bcm6345-uart"; + reg = <0x10000120 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <39>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + timer: syscon@10000040 { compatible = "syscon"; reg = <0x10000040 0x2c>; native-endian; }; - reboot { + reboot: syscon-reboot@10000068 { compatible = "syscon-reboot"; regmap = <&timer>; offset = <0x28>; @@ -91,5 +100,24 @@ reg = <0x10000800 0x24>; status = "disabled"; }; + + ehci: usb@10002500 { + compatible = "brcm,bcm6328-ehci", "generic-ehci"; + reg = <0x10002500 0x100>; + big-endian; + interrupt-parent = <&periph_intc>; + interrupts = <42>; + status = "disabled"; + }; + + ohci: usb@10002600 { + compatible = "brcm,bcm6328-ohci", "generic-ohci"; + reg = <0x10002600 0x100>; + big-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <41>; + status = "disabled"; + }; }; }; -- cgit v1.2.3-59-g8ed1b From 2d52ee82b4756d11565e94b8c09e77bb8c036a11 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:57:49 +0200 Subject: MIPS: BMIPS: Improve BCM6368 device tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unneeded leds0 alias. - Switch to bcm6345-l1-intc interrupt controller. - Use interrupt-controller instead of periph_intc and cpu_intc. - Add uart1 node. - Single ohci and ehci nodes. - Avoid using underscores in node names. - Rename uart aliases to serial. - Remove blank line in cpus node. [ralf@linux-mips.org: fix references in bcm96368mvwg.dts so the file keeps building.] Signed-off-by: Álvaro Fernández Rojas Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm6368.dtsi | 32 ++++++++++++++++++++------------ arch/mips/boot/dts/brcm/bcm96368mvwg.dts | 4 ++-- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi index 1f6b9b5cddb4..d0e3a70b32e2 100644 --- a/arch/mips/boot/dts/brcm/bcm6368.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi @@ -20,11 +20,10 @@ device_type = "cpu"; reg = <1>; }; - }; clocks { - periph_clk: periph_clk { + periph_clk: periph-clk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <50000000>; @@ -32,11 +31,11 @@ }; aliases { - leds0 = &leds0; - uart0 = &uart0; + serial0 = &uart0; + serial1 = &uart1; }; - cpu_intc: cpu_intc { + cpu_intc: interrupt-controller { #address-cells = <0>; compatible = "mti,cpu-interrupt-controller"; @@ -64,16 +63,16 @@ mask = <0x1>; }; - periph_intc: periph_intc@10000020 { - compatible = "brcm,bcm3380-l2-intc"; - reg = <0x10000024 0x4 0x1000002c 0x4>, - <0x10000020 0x4 0x10000028 0x4>; + periph_intc: interrupt-controller@10000020 { + compatible = "brcm,bcm6345-l1-intc"; + reg = <0x10000020 0x10>, + <0x10000030 0x10>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&cpu_intc>; - interrupts = <2>; + interrupts = <2>, <3>; }; leds0: led-controller@100000d0 { @@ -93,7 +92,16 @@ status = "disabled"; }; - ehci0: usb@10001500 { + uart1: serial@10000120 { + compatible = "brcm,bcm6345-uart"; + reg = <0x10000120 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <3>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + ehci: usb@10001500 { compatible = "brcm,bcm6368-ehci", "generic-ehci"; reg = <0x10001500 0x100>; big-endian; @@ -102,7 +110,7 @@ status = "disabled"; }; - ohci0: usb@10001600 { + ohci: usb@10001600 { compatible = "brcm,bcm6368-ohci", "generic-ohci"; reg = <0x10001600 0x100>; big-endian; diff --git a/arch/mips/boot/dts/brcm/bcm96368mvwg.dts b/arch/mips/boot/dts/brcm/bcm96368mvwg.dts index 0e890c28fe5c..8c71c6845730 100644 --- a/arch/mips/boot/dts/brcm/bcm96368mvwg.dts +++ b/arch/mips/boot/dts/brcm/bcm96368mvwg.dts @@ -22,10 +22,10 @@ }; /* FIXME: need to set up USB_CTRL registers first */ -&ehci0 { +&ehci { status = "disabled"; }; -&ohci0 { +&ohci { status = "disabled"; }; -- cgit v1.2.3-59-g8ed1b From 0e8c1a3247629ecb0e344655124fd59682410913 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Fri, 19 Feb 2016 17:04:07 -0800 Subject: MIPS: Octeon: Mark some functions __init in smp.c octeon_smp_setup and octeon_prepare_cpus are just used during initialization period, so mark them as __init. And, octeon_prepare_cpus is just used in smp.c, so make it static as well. Signed-off-by: Yang Shi Cc: david.daney@cavium.com Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12574/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 32c0cce73ed7..dff88aa7e377 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -127,7 +127,7 @@ static void octeon_smp_hotplug_setup(void) #endif } -static void octeon_smp_setup(void) +static void __init octeon_smp_setup(void) { const int coreid = cvmx_get_core_num(); int cpus; @@ -228,7 +228,7 @@ static void octeon_init_secondary(void) * Callout to firmware before smp_init * */ -void octeon_prepare_cpus(unsigned int max_cpus) +static void __init octeon_prepare_cpus(unsigned int max_cpus) { /* * Only the low order mailbox bits are used for IPIs, leave -- cgit v1.2.3-59-g8ed1b From 987e5b834467c9251ca584febda65ef8f66351a9 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 8 Feb 2016 18:43:51 +0000 Subject: MIPS: Fix uapi include in exported asm/siginfo.h Since commit 8cb48fe169dd ("MIPS: Provide correct siginfo_t.si_stime"), MIPS' uapi/asm/siginfo.h has included uapi/asm-generic/siginfo.h directly before defining MIPS' struct siginfo, in order to get the necessary definitions needed for the siginfo struct without the generic copy_siginfo() hitting compiler errors due to struct siginfo not yet being defined. Now that the generic copy_siginfo() is moved out to linux/signal.h we can safely include asm-generic/siginfo.h before defining the MIPS specific struct siginfo, which avoids the uapi/ include as well as breakage due to generic copy_siginfo() being defined before struct siginfo. Reported-by: Christopher Ferris Fixes: 8cb48fe169dd ("MIPS: Provide correct siginfo_t.si_stime") Signed-off-by: James Hogan Cc: Petr Malat Cc: linux-mips@linux-mips.org Cc: # 4.0- Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/siginfo.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index 9db5bda8df3f..8069cf766603 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -28,7 +28,7 @@ #define __ARCH_SIGSYS -#include +#include /* We can't use generic siginfo_t, because our si_code and si_errno are swapped */ typedef struct siginfo { @@ -123,6 +123,4 @@ typedef struct siginfo { #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */ #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */ -#include - #endif /* _UAPI_ASM_SIGINFO_H */ -- cgit v1.2.3-59-g8ed1b From 2e5832ab589459265e70163a7dea3abdc1429eb7 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 Nov 2015 00:48:39 +0000 Subject: MIPS: ELF: Restructure personality macros Update the ELF personality macros used for individual ABIs to make actions in the same order across all of them and match formatting too. Signed-off-by: Maciej W. Rozycki Cc: Andrew Morton Cc: Matthew Fortune Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 1bcbadb445fb..1fba19747fa9 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -305,17 +305,16 @@ extern struct mips_abi mips_abi_n32; #define SET_PERSONALITY2(ex, state) \ do { \ - if (personality(current->personality) != PER_LINUX) \ - set_personality(PER_LINUX); \ - \ clear_thread_flag(TIF_HYBRID_FPREGS); \ set_thread_flag(TIF_32BIT_FPREGS); \ \ - mips_set_personality_fp(state); \ - \ current->thread.abi = &mips_abi; \ \ + mips_set_personality_fp(state); \ mips_set_personality_nan(state); \ + \ + if (personality(current->personality) != PER_LINUX) \ + set_personality(PER_LINUX); \ } while (0) #endif /* CONFIG_32BIT */ @@ -326,6 +325,7 @@ do { \ #define __SET_PERSONALITY32_N32() \ do { \ set_thread_flag(TIF_32BIT_ADDR); \ + \ current->thread.abi = &mips_abi_n32; \ } while (0) #else @@ -341,9 +341,9 @@ do { \ clear_thread_flag(TIF_HYBRID_FPREGS); \ set_thread_flag(TIF_32BIT_FPREGS); \ \ - mips_set_personality_fp(state); \ - \ current->thread.abi = &mips_abi_32; \ + \ + mips_set_personality_fp(state); \ } while (0) #else #define __SET_PERSONALITY32_O32(ex, state) \ -- cgit v1.2.3-59-g8ed1b From acd9e20cd9d0e6af5680e1870a966d8082a1130a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 Nov 2015 00:48:48 +0000 Subject: MIPS: math-emu: Always propagate sNaN payload in quieting Propagate sNaN payload in quieting in the legacy-NaN mode as well. If clearing the quiet bit would produce infinity, then set the next lower trailing significand field bit, matching the SB-1 and BMIPS5000 hardware implementations. Some other MIPS FPU hardware implementations do produce the default qNaN bit pattern instead. This reverts some changes made for semantics preservation with commit dc3ddf42 [MIPS: math-emu: Update sNaN quieting handlers], consequently bringing back most of the semantics from before commit fdffbafb [Lots of FPU bug fixes from Kjeld Borch Egevang.], except from the qNaN produced in the infinity case. Previously the default qNaN bit pattern was produced in that case. Signed-off-by: Maciej W. Rozycki Cc: Andrew Morton Cc: Matthew Fortune Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11483/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/ieee754dp.c | 9 ++++++--- arch/mips/math-emu/ieee754sp.c | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 47d26c805eac..465a0342ed4c 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -54,10 +54,13 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r) assert(ieee754dp_issnan(r)); ieee754_setcx(IEEE754_INVALID_OPERATION); - if (ieee754_csr.nan2008) + if (ieee754_csr.nan2008) { DPMANT(r) |= DP_MBIT(DP_FBITS - 1); - else - r = ieee754dp_indef(); + } else { + DPMANT(r) &= ~DP_MBIT(DP_FBITS - 1); + if (!ieee754dp_isnan(r)) + DPMANT(r) |= DP_MBIT(DP_FBITS - 2); + } return r; } diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index e0b2c450b963..860e9162097f 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -54,10 +54,13 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) assert(ieee754sp_issnan(r)); ieee754_setcx(IEEE754_INVALID_OPERATION); - if (ieee754_csr.nan2008) + if (ieee754_csr.nan2008) { SPMANT(r) |= SP_MBIT(SP_FBITS - 1); - else - r = ieee754sp_indef(); + } else { + SPMANT(r) &= ~SP_MBIT(SP_FBITS - 1); + if (!ieee754sp_isnan(r)) + SPMANT(r) |= SP_MBIT(SP_FBITS - 2); + } return r; } -- cgit v1.2.3-59-g8ed1b From ba837d387195ea043900d2101cf90bcc083cff1b Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 15 Feb 2016 15:35:20 +0100 Subject: MIPS: module: fix incorrect IS_ERR_VALUE macro usages IS_ERR_VALUE macro should be used only with unsigned long type. Specifically it works incorrectly with longer types. The patch follows conclusion from discussion on LKML [1][2]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2120927 [2]: http://permalink.gmane.org/gmane.linux.kernel/2150581 [ralf@linux-mips.org: While it may not immediately be obvious, the type of st_value in the end is an unsigned long equivalent so the invocation of IS_ERR_VALUE() was valid but I'm applying the patch anyway for clarity.] Signed-off-by: Andrzej Hajda Cc: Bartlomiej Zolnierkiewicz Cc: Marek Szyprowski Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12553/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/module-rela.c | 2 +- arch/mips/kernel/module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c index b3611426b128..781168834456 100644 --- a/arch/mips/kernel/module-rela.c +++ b/arch/mips/kernel/module-rela.c @@ -170,7 +170,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, /* This is the symbol it is referring to */ sym = (Elf_Sym *)sechdrs[symindex].sh_addr + ELF_MIPS_R_SYM(rel[i]); - if (IS_ERR_VALUE(sym->st_value)) { + if (sym->st_value >= -MAX_ERRNO) { /* Ignore unresolved weak symbol */ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) continue; diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index ff5d97d2e670..79850e376ef6 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -263,7 +263,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, /* This is the symbol it is referring to */ sym = (Elf_Sym *)sechdrs[symindex].sh_addr + ELF_MIPS_R_SYM(rel[i]); - if (IS_ERR_VALUE(sym->st_value)) { + if (sym->st_value >= -MAX_ERRNO) { /* Ignore unresolved weak symbol */ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) continue; -- cgit v1.2.3-59-g8ed1b From e233c733786a8ca70cd12cc30aeb80e5b390ad71 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:38 +0000 Subject: MIPS: Add and use CAUSEF_WP definition do_watch() clears bit 22 of cause without using a CAUSEF_* definition from mipsregs.h. Add a definition for this bit (CAUSEF_WP) and make use of it. Also use clear_c0_cause() instead of manual read/modify/write. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12728/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 2 ++ arch/mips/kernel/traps.c | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index ca251f6fea8e..c08b6f798f8f 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -390,6 +390,8 @@ #define CAUSEF_IP7 (_ULCAST_(1) << 15) #define CAUSEB_FDCI 21 #define CAUSEF_FDCI (_ULCAST_(1) << 21) +#define CAUSEB_WP 22 +#define CAUSEF_WP (_ULCAST_(1) << 22) #define CAUSEB_IV 23 #define CAUSEF_IV (_ULCAST_(1) << 23) #define CAUSEB_PCI 26 diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 4358f025b752..dcda63e65854 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1498,16 +1498,13 @@ asmlinkage void do_watch(struct pt_regs *regs) { siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT }; enum ctx_state prev_state; - u32 cause; prev_state = exception_enter(); /* * Clear WP (bit 22) bit of cause register so we don't loop * forever. */ - cause = read_c0_cause(); - cause &= ~(1 << 22); - write_c0_cause(cause); + clear_c0_cause(CAUSEF_WP); /* * If the current thread has the watch registers loaded, save -- cgit v1.2.3-59-g8ed1b From 50af501cd84b4e005fd54c351184ec89cfc940e4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:39 +0000 Subject: MIPS: Add and use watch register field definitions The files watch.c and ptrace.c contain various magic masks for WatchLo/WatchHi register fields. Add some definitions to mipsregs.h for these registers and make use of them in both watch.c and ptrace.c, hopefully making them more readable. Signed-off-by: James Hogan Reviewed-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12729/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 18 ++++++++++ arch/mips/kernel/ptrace.c | 7 ++-- arch/mips/kernel/watch.c | 74 ++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index c08b6f798f8f..aea90631a301 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -648,6 +648,24 @@ /* FTLB probability bits for R6 */ #define MIPS_CONF7_FTLBP_SHIFT (18) +/* WatchLo* register definitions */ +#define MIPS_WATCHLO_IRW (_ULCAST_(0x7) << 0) + +/* WatchHi* register definitions */ +#define MIPS_WATCHHI_M (_ULCAST_(1) << 31) +#define MIPS_WATCHHI_G (_ULCAST_(1) << 30) +#define MIPS_WATCHHI_WM (_ULCAST_(0x3) << 28) +#define MIPS_WATCHHI_WM_R_RVA (_ULCAST_(0) << 28) +#define MIPS_WATCHHI_WM_R_GPA (_ULCAST_(1) << 28) +#define MIPS_WATCHHI_WM_G_GVA (_ULCAST_(2) << 28) +#define MIPS_WATCHHI_EAS (_ULCAST_(0x3) << 24) +#define MIPS_WATCHHI_ASID (_ULCAST_(0xff) << 16) +#define MIPS_WATCHHI_MASK (_ULCAST_(0x1ff) << 3) +#define MIPS_WATCHHI_I (_ULCAST_(1) << 2) +#define MIPS_WATCHHI_R (_ULCAST_(1) << 1) +#define MIPS_WATCHHI_W (_ULCAST_(1) << 0) +#define MIPS_WATCHHI_IRW (_ULCAST_(0x7) << 0) + /* MAAR bit definitions */ #define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12) #define MIPS_MAAR_ADDR_SHIFT 12 diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index a5279b2f3198..48c0534c4d15 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -210,7 +210,8 @@ int ptrace_get_watch_regs(struct task_struct *child, for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __put_user(child->thread.watch.mips3264.watchlo[i], &addr->WATCH_STYLE.watchlo[i]); - __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, + __put_user(child->thread.watch.mips3264.watchhi[i] & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW), &addr->WATCH_STYLE.watchhi[i]); __put_user(boot_cpu_data.watch_reg_masks[i], &addr->WATCH_STYLE.watch_masks[i]); @@ -252,12 +253,12 @@ int ptrace_set_watch_regs(struct task_struct *child, } #endif __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]); - if (ht[i] & ~0xff8) + if (ht[i] & ~MIPS_WATCHHI_MASK) return -EINVAL; } /* Install them. */ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { - if (lt[i] & 7) + if (lt[i] & MIPS_WATCHLO_IRW) watch_active = 1; child->thread.watch.mips3264.watchlo[i] = lt[i]; /* Set the G bit. */ diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index 9b78e375118e..19fcab7348b1 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -25,16 +25,20 @@ void mips_install_watch_registers(struct task_struct *t) write_c0_watchlo3(watches->watchlo[3]); /* Write 1 to the I, R, and W bits to clear them, and 1 to G so all ASIDs are trapped. */ - write_c0_watchhi3(0x40000007 | watches->watchhi[3]); + write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[3]); case 3: write_c0_watchlo2(watches->watchlo[2]); - write_c0_watchhi2(0x40000007 | watches->watchhi[2]); + write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[2]); case 2: write_c0_watchlo1(watches->watchlo[1]); - write_c0_watchhi1(0x40000007 | watches->watchhi[1]); + write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[1]); case 1: write_c0_watchlo0(watches->watchlo[0]); - write_c0_watchhi0(0x40000007 | watches->watchhi[0]); + write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[0]); } } @@ -51,22 +55,26 @@ void mips_read_watch_registers(void) default: BUG(); case 4: - watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff); + watches->watchhi[3] = (read_c0_watchhi3() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 3: - watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff); + watches->watchhi[2] = (read_c0_watchhi2() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 2: - watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff); + watches->watchhi[1] = (read_c0_watchhi1() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 1: - watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff); + watches->watchhi[0] = (read_c0_watchhi0() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); } if (current_cpu_data.watch_reg_use_cnt == 1 && - (watches->watchhi[0] & 7) == 0) { + (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) { /* Pathological case of release 1 architecture that * doesn't set the condition bits. We assume that * since we got here, the watch condition was met and * signal that the conditions requested in watchlo * were met. */ - watches->watchhi[0] |= (watches->watchlo[0] & 7); + watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW); } } @@ -109,86 +117,86 @@ void mips_probe_watch_registers(struct cpuinfo_mips *c) * Check which of the I,R and W bits are supported, then * disable the register. */ - write_c0_watchlo0(7); + write_c0_watchlo0(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo0(); write_c0_watchlo0(0); - c->watch_reg_masks[0] = t & 7; + c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW; /* Write the mask bits and read them back to determine which * can be used. */ c->watch_reg_count = 1; c->watch_reg_use_cnt = 1; t = read_c0_watchhi0(); - write_c0_watchhi0(t | 0xff8); + write_c0_watchhi0(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi0(); - c->watch_reg_masks[0] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo1(7); + write_c0_watchlo1(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo1(); write_c0_watchlo1(0); - c->watch_reg_masks[1] = t & 7; + c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 2; c->watch_reg_use_cnt = 2; t = read_c0_watchhi1(); - write_c0_watchhi1(t | 0xff8); + write_c0_watchhi1(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi1(); - c->watch_reg_masks[1] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo2(7); + write_c0_watchlo2(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo2(); write_c0_watchlo2(0); - c->watch_reg_masks[2] = t & 7; + c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 3; c->watch_reg_use_cnt = 3; t = read_c0_watchhi2(); - write_c0_watchhi2(t | 0xff8); + write_c0_watchhi2(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi2(); - c->watch_reg_masks[2] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo3(7); + write_c0_watchlo3(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo3(); write_c0_watchlo3(0); - c->watch_reg_masks[3] = t & 7; + c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 4; c->watch_reg_use_cnt = 4; t = read_c0_watchhi3(); - write_c0_watchhi3(t | 0xff8); + write_c0_watchhi3(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi3(); - c->watch_reg_masks[3] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; /* We use at most 4, but probe and report up to 8. */ c->watch_reg_count = 5; t = read_c0_watchhi4(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 6; t = read_c0_watchhi5(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 7; t = read_c0_watchhi6(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 8; -- cgit v1.2.3-59-g8ed1b From 44896afe214e780e172f1bbbea7a2e6d087c908d Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 27 Jan 2016 14:56:06 +0100 Subject: MIPS: BCM1480: bcm1480_regs.h: strip redundant comments Strip some comments which probably meant to repeat the same value of the define; they also contained a confusing 0x0x prefix. Signed-off-by: Antonio Ospite Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12254/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/sibyte/bcm1480_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/sibyte/bcm1480_regs.h b/arch/mips/include/asm/sibyte/bcm1480_regs.h index ec0dacf6f0cb..32a84837b8fa 100644 --- a/arch/mips/include/asm/sibyte/bcm1480_regs.h +++ b/arch/mips/include/asm/sibyte/bcm1480_regs.h @@ -415,8 +415,8 @@ (cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING) #define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu, reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg)) -#define R_BCM1480_IMR_ALIAS_MAILBOX_0 0x0000 /* 0x0x0 */ -#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET 0x0008 /* 0x0x8 */ +#define R_BCM1480_IMR_ALIAS_MAILBOX_0 0x0000 +#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET 0x0008 /* * these macros work together to build the address of a mailbox -- cgit v1.2.3-59-g8ed1b From d0514728247b91476a525a064f8b3c2f0c47bec4 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 7 Oct 2015 14:08:00 +0800 Subject: MIPS: Loongson-3: Move chipset ACPI code from drivers to arch SB700/SB710/SB800 chipset ACPI code is mostly Loongson-3 specific routines rather than a "platform driver". Signed-off-by: Huacai Chen Cc: John Crispin Cc: Steven J. Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11273/ Signed-off-by: Ralf Baechle --- arch/mips/loongson64/loongson-3/Makefile | 2 +- arch/mips/loongson64/loongson-3/acpi_init.c | 150 ++++++++++++++++++++++++++++ drivers/platform/mips/Kconfig | 4 - drivers/platform/mips/Makefile | 1 - drivers/platform/mips/acpi_init.c | 150 ---------------------------- 5 files changed, 151 insertions(+), 156 deletions(-) create mode 100644 arch/mips/loongson64/loongson-3/acpi_init.c delete mode 100644 drivers/platform/mips/acpi_init.c (limited to 'arch') diff --git a/arch/mips/loongson64/loongson-3/Makefile b/arch/mips/loongson64/loongson-3/Makefile index 622fead5ebc9..44bc1482158b 100644 --- a/arch/mips/loongson64/loongson-3/Makefile +++ b/arch/mips/loongson64/loongson-3/Makefile @@ -1,7 +1,7 @@ # # Makefile for Loongson-3 family machines # -obj-y += irq.o cop2-ex.o platform.o +obj-y += irq.o cop2-ex.o platform.o acpi_init.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/mips/loongson64/loongson-3/acpi_init.c b/arch/mips/loongson64/loongson-3/acpi_init.c new file mode 100644 index 000000000000..dbdad79ead8f --- /dev/null +++ b/arch/mips/loongson64/loongson-3/acpi_init.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include + +#define SBX00_ACPI_IO_BASE 0x800 +#define SBX00_ACPI_IO_SIZE 0x100 + +#define ACPI_PM_EVT_BLK (SBX00_ACPI_IO_BASE + 0x00) /* 4 bytes */ +#define ACPI_PM_CNT_BLK (SBX00_ACPI_IO_BASE + 0x04) /* 2 bytes */ +#define ACPI_PMA_CNT_BLK (SBX00_ACPI_IO_BASE + 0x0F) /* 1 byte */ +#define ACPI_PM_TMR_BLK (SBX00_ACPI_IO_BASE + 0x18) /* 4 bytes */ +#define ACPI_GPE0_BLK (SBX00_ACPI_IO_BASE + 0x10) /* 8 bytes */ +#define ACPI_END (SBX00_ACPI_IO_BASE + 0x80) + +#define PM_INDEX 0xCD6 +#define PM_DATA 0xCD7 +#define PM2_INDEX 0xCD0 +#define PM2_DATA 0xCD1 + +/* + * SCI interrupt need acpi space, allocate here + */ + +static int __init register_acpi_resource(void) +{ + request_region(SBX00_ACPI_IO_BASE, SBX00_ACPI_IO_SIZE, "acpi"); + return 0; +} + +static void pmio_write_index(u16 index, u8 reg, u8 value) +{ + outb(reg, index); + outb(value, index + 1); +} + +static u8 pmio_read_index(u16 index, u8 reg) +{ + outb(reg, index); + return inb(index + 1); +} + +void pm_iowrite(u8 reg, u8 value) +{ + pmio_write_index(PM_INDEX, reg, value); +} +EXPORT_SYMBOL(pm_iowrite); + +u8 pm_ioread(u8 reg) +{ + return pmio_read_index(PM_INDEX, reg); +} +EXPORT_SYMBOL(pm_ioread); + +void pm2_iowrite(u8 reg, u8 value) +{ + pmio_write_index(PM2_INDEX, reg, value); +} +EXPORT_SYMBOL(pm2_iowrite); + +u8 pm2_ioread(u8 reg) +{ + return pmio_read_index(PM2_INDEX, reg); +} +EXPORT_SYMBOL(pm2_ioread); + +static void acpi_hw_clear_status(void) +{ + u16 value; + + /* PMStatus: Clear WakeStatus/PwrBtnStatus */ + value = inw(ACPI_PM_EVT_BLK); + value |= (1 << 8 | 1 << 15); + outw(value, ACPI_PM_EVT_BLK); + + /* GPEStatus: Clear all generated events */ + outl(inl(ACPI_GPE0_BLK), ACPI_GPE0_BLK); +} + +void acpi_registers_setup(void) +{ + u32 value; + + /* PM Status Base */ + pm_iowrite(0x20, ACPI_PM_EVT_BLK & 0xff); + pm_iowrite(0x21, ACPI_PM_EVT_BLK >> 8); + + /* PM Control Base */ + pm_iowrite(0x22, ACPI_PM_CNT_BLK & 0xff); + pm_iowrite(0x23, ACPI_PM_CNT_BLK >> 8); + + /* GPM Base */ + pm_iowrite(0x28, ACPI_GPE0_BLK & 0xff); + pm_iowrite(0x29, ACPI_GPE0_BLK >> 8); + + /* ACPI End */ + pm_iowrite(0x2e, ACPI_END & 0xff); + pm_iowrite(0x2f, ACPI_END >> 8); + + /* IO Decode: When AcpiDecodeEnable set, South-Bridge uses the contents + * of the PM registers at index 0x20~0x2B to decode ACPI I/O address. */ + pm_iowrite(0x0e, 1 << 3); + + /* SCI_EN set */ + outw(1, ACPI_PM_CNT_BLK); + + /* Enable to generate SCI */ + pm_iowrite(0x10, pm_ioread(0x10) | 1); + + /* GPM3/GPM9 enable */ + value = inl(ACPI_GPE0_BLK + 4); + outl(value | (1 << 14) | (1 << 22), ACPI_GPE0_BLK + 4); + + /* Set GPM9 as input */ + pm_iowrite(0x8d, pm_ioread(0x8d) & (~(1 << 1))); + + /* Set GPM9 as non-output */ + pm_iowrite(0x94, pm_ioread(0x94) | (1 << 3)); + + /* GPM3 config ACPI trigger SCIOUT */ + pm_iowrite(0x33, pm_ioread(0x33) & (~(3 << 4))); + + /* GPM9 config ACPI trigger SCIOUT */ + pm_iowrite(0x3d, pm_ioread(0x3d) & (~(3 << 2))); + + /* GPM3 config falling edge trigger */ + pm_iowrite(0x37, pm_ioread(0x37) & (~(1 << 6))); + + /* No wait for STPGNT# in ACPI Sx state */ + pm_iowrite(0x7c, pm_ioread(0x7c) | (1 << 6)); + + /* Set GPM3 pull-down enable */ + value = pm2_ioread(0xf6); + value |= ((1 << 7) | (1 << 3)); + pm2_iowrite(0xf6, value); + + /* Set GPM9 pull-down enable */ + value = pm2_ioread(0xf8); + value |= ((1 << 5) | (1 << 1)); + pm2_iowrite(0xf8, value); +} + +int __init sbx00_acpi_init(void) +{ + register_acpi_resource(); + acpi_registers_setup(); + acpi_hw_clear_status(); + + return 0; +} diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig index 125e569017be..b3ae30a4c67b 100644 --- a/drivers/platform/mips/Kconfig +++ b/drivers/platform/mips/Kconfig @@ -15,10 +15,6 @@ menuconfig MIPS_PLATFORM_DEVICES if MIPS_PLATFORM_DEVICES -config MIPS_ACPI - bool - default y if LOONGSON_MACH3X - config CPU_HWMON tristate "Loongson CPU HWMon Driver" depends on LOONGSON_MACH3X diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile index 43412849b195..8dfd03924c37 100644 --- a/drivers/platform/mips/Makefile +++ b/drivers/platform/mips/Makefile @@ -1,2 +1 @@ -obj-$(CONFIG_MIPS_ACPI) += acpi_init.o obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o diff --git a/drivers/platform/mips/acpi_init.c b/drivers/platform/mips/acpi_init.c deleted file mode 100644 index dbdad79ead8f..000000000000 --- a/drivers/platform/mips/acpi_init.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include - -#define SBX00_ACPI_IO_BASE 0x800 -#define SBX00_ACPI_IO_SIZE 0x100 - -#define ACPI_PM_EVT_BLK (SBX00_ACPI_IO_BASE + 0x00) /* 4 bytes */ -#define ACPI_PM_CNT_BLK (SBX00_ACPI_IO_BASE + 0x04) /* 2 bytes */ -#define ACPI_PMA_CNT_BLK (SBX00_ACPI_IO_BASE + 0x0F) /* 1 byte */ -#define ACPI_PM_TMR_BLK (SBX00_ACPI_IO_BASE + 0x18) /* 4 bytes */ -#define ACPI_GPE0_BLK (SBX00_ACPI_IO_BASE + 0x10) /* 8 bytes */ -#define ACPI_END (SBX00_ACPI_IO_BASE + 0x80) - -#define PM_INDEX 0xCD6 -#define PM_DATA 0xCD7 -#define PM2_INDEX 0xCD0 -#define PM2_DATA 0xCD1 - -/* - * SCI interrupt need acpi space, allocate here - */ - -static int __init register_acpi_resource(void) -{ - request_region(SBX00_ACPI_IO_BASE, SBX00_ACPI_IO_SIZE, "acpi"); - return 0; -} - -static void pmio_write_index(u16 index, u8 reg, u8 value) -{ - outb(reg, index); - outb(value, index + 1); -} - -static u8 pmio_read_index(u16 index, u8 reg) -{ - outb(reg, index); - return inb(index + 1); -} - -void pm_iowrite(u8 reg, u8 value) -{ - pmio_write_index(PM_INDEX, reg, value); -} -EXPORT_SYMBOL(pm_iowrite); - -u8 pm_ioread(u8 reg) -{ - return pmio_read_index(PM_INDEX, reg); -} -EXPORT_SYMBOL(pm_ioread); - -void pm2_iowrite(u8 reg, u8 value) -{ - pmio_write_index(PM2_INDEX, reg, value); -} -EXPORT_SYMBOL(pm2_iowrite); - -u8 pm2_ioread(u8 reg) -{ - return pmio_read_index(PM2_INDEX, reg); -} -EXPORT_SYMBOL(pm2_ioread); - -static void acpi_hw_clear_status(void) -{ - u16 value; - - /* PMStatus: Clear WakeStatus/PwrBtnStatus */ - value = inw(ACPI_PM_EVT_BLK); - value |= (1 << 8 | 1 << 15); - outw(value, ACPI_PM_EVT_BLK); - - /* GPEStatus: Clear all generated events */ - outl(inl(ACPI_GPE0_BLK), ACPI_GPE0_BLK); -} - -void acpi_registers_setup(void) -{ - u32 value; - - /* PM Status Base */ - pm_iowrite(0x20, ACPI_PM_EVT_BLK & 0xff); - pm_iowrite(0x21, ACPI_PM_EVT_BLK >> 8); - - /* PM Control Base */ - pm_iowrite(0x22, ACPI_PM_CNT_BLK & 0xff); - pm_iowrite(0x23, ACPI_PM_CNT_BLK >> 8); - - /* GPM Base */ - pm_iowrite(0x28, ACPI_GPE0_BLK & 0xff); - pm_iowrite(0x29, ACPI_GPE0_BLK >> 8); - - /* ACPI End */ - pm_iowrite(0x2e, ACPI_END & 0xff); - pm_iowrite(0x2f, ACPI_END >> 8); - - /* IO Decode: When AcpiDecodeEnable set, South-Bridge uses the contents - * of the PM registers at index 0x20~0x2B to decode ACPI I/O address. */ - pm_iowrite(0x0e, 1 << 3); - - /* SCI_EN set */ - outw(1, ACPI_PM_CNT_BLK); - - /* Enable to generate SCI */ - pm_iowrite(0x10, pm_ioread(0x10) | 1); - - /* GPM3/GPM9 enable */ - value = inl(ACPI_GPE0_BLK + 4); - outl(value | (1 << 14) | (1 << 22), ACPI_GPE0_BLK + 4); - - /* Set GPM9 as input */ - pm_iowrite(0x8d, pm_ioread(0x8d) & (~(1 << 1))); - - /* Set GPM9 as non-output */ - pm_iowrite(0x94, pm_ioread(0x94) | (1 << 3)); - - /* GPM3 config ACPI trigger SCIOUT */ - pm_iowrite(0x33, pm_ioread(0x33) & (~(3 << 4))); - - /* GPM9 config ACPI trigger SCIOUT */ - pm_iowrite(0x3d, pm_ioread(0x3d) & (~(3 << 2))); - - /* GPM3 config falling edge trigger */ - pm_iowrite(0x37, pm_ioread(0x37) & (~(1 << 6))); - - /* No wait for STPGNT# in ACPI Sx state */ - pm_iowrite(0x7c, pm_ioread(0x7c) | (1 << 6)); - - /* Set GPM3 pull-down enable */ - value = pm2_ioread(0xf6); - value |= ((1 << 7) | (1 << 3)); - pm2_iowrite(0xf6, value); - - /* Set GPM9 pull-down enable */ - value = pm2_ioread(0xf8); - value |= ((1 << 5) | (1 << 1)); - pm2_iowrite(0xf8, value); -} - -int __init sbx00_acpi_init(void) -{ - register_acpi_resource(); - acpi_registers_setup(); - acpi_hw_clear_status(); - - return 0; -} -- cgit v1.2.3-59-g8ed1b From 24653515e5d2cb07772919599ad799ce50f8af4f Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 17 Mar 2016 20:41:07 +0800 Subject: MIPS: Loongson-3: Adjust irq dispatch to speedup processing This patch adjust the logic in mach_irq_dispatch(), allow multiple IPs handled in the same dispatching. This can speedup interrupt processing. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12891/ Signed-off-by: Ralf Baechle --- arch/mips/loongson64/loongson-3/irq.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/loongson64/loongson-3/irq.c b/arch/mips/loongson64/loongson-3/irq.c index 0f75b6b3d218..8e7649088353 100644 --- a/arch/mips/loongson64/loongson-3/irq.c +++ b/arch/mips/loongson64/loongson-3/irq.c @@ -24,19 +24,21 @@ static void ht_irqdispatch(void) } } +#define UNUSED_IPS (CAUSEF_IP5 | CAUSEF_IP4 | CAUSEF_IP1 | CAUSEF_IP0) + void mach_irq_dispatch(unsigned int pending) { if (pending & CAUSEF_IP7) do_IRQ(LOONGSON_TIMER_IRQ); #if defined(CONFIG_SMP) - else if (pending & CAUSEF_IP6) + if (pending & CAUSEF_IP6) loongson3_ipi_interrupt(NULL); #endif - else if (pending & CAUSEF_IP3) + if (pending & CAUSEF_IP3) ht_irqdispatch(); - else if (pending & CAUSEF_IP2) + if (pending & CAUSEF_IP2) do_IRQ(LOONGSON_UART_IRQ); - else { + if (pending & UNUSED_IPS) { pr_err("%s : spurious interrupt\n", __func__); spurious_interrupt(); } -- cgit v1.2.3-59-g8ed1b From b2edcfc814017eb278e29bfdc72844f0434dd8b1 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:09 +0800 Subject: MIPS: Loongson: Add Loongson-3A R2 basic support Loongson-3 CPU family: Code-name Brand-name PRId Loongson-3A R1 Loongson-3A1000 0x6305 Loongson-3A R2 Loongson-3A2000 0x6308 Loongson-3B R1 Loongson-3B1000 0x6306 Loongson-3B R2 Loongson-3B1500 0x6307 Features of R2 revision of Loongson-3A: - Primary cache includes I-Cache, D-Cache and V-Cache (Victim Cache). - I-Cache, D-Cache and V-Cache are 16-way set-associative, linesize is 64 bytes. - 64 entries of VTLB (classic TLB), 1024 entries of FTLB (8-way set-associative). - Supports DSP/DSPv2 instructions, UserLocal register and Read-Inhibit/ Execute-Inhibit. [ralf@linux-mips.org: Resolved merge conflicts.] Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12751/ Patchwork: https://patchwork.linux-mips.org/patch/13136/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/include/asm/cacheops.h | 6 ++ arch/mips/include/asm/cpu-info.h | 1 + arch/mips/include/asm/cpu.h | 4 +- .../asm/mach-loongson64/cpu-feature-overrides.h | 18 +--- .../asm/mach-loongson64/kernel-entry-init.h | 6 +- arch/mips/include/asm/mipsregs.h | 2 + arch/mips/include/asm/pgtable.h | 4 +- arch/mips/kernel/cpu-probe.c | 38 +++++++- arch/mips/kernel/idle.c | 5 + arch/mips/kernel/traps.c | 3 +- arch/mips/loongson64/common/env.c | 7 +- arch/mips/loongson64/loongson-3/smp.c | 106 +++++++++++++++++++-- arch/mips/mm/c-r4k.c | 27 ++++++ drivers/platform/mips/cpu_hwmon.c | 4 +- 15 files changed, 201 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fbd63ff8eba4..adcc97ea4392 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1354,6 +1354,7 @@ config CPU_LOONGSON3 select CPU_SUPPORTS_HUGEPAGES select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC + select MIPS_PGD_C0_CONTEXT select ARCH_REQUIRE_GPIOLIB help The Loongson 3 processor implements the MIPS64R2 instruction @@ -1823,6 +1824,7 @@ config CPU_BMIPS5000 config SYS_HAS_CPU_LOONGSON3 bool select CPU_SUPPORTS_CPUFREQ + select CPU_HAS_RIXI config SYS_HAS_CPU_LOONGSON2E bool diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index c3212ff26723..8031fbc6b69a 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h @@ -21,6 +21,7 @@ #define Cache_I 0x00 #define Cache_D 0x01 #define Cache_T 0x02 +#define Cache_V 0x02 /* Loongson-3 */ #define Cache_S 0x03 #define Index_Writeback_Inv 0x00 @@ -107,4 +108,9 @@ */ #define Hit_Invalidate_I_Loongson2 (Cache_I | 0x00) +/* + * Loongson3-specific cacheops + */ +#define Index_Writeback_Inv_V (Cache_V | Index_Writeback_Inv) + #endif /* __ASM_CACHEOPS_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 9ec81684b1b8..b090aa51d644 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -60,6 +60,7 @@ struct cpuinfo_mips { int tlbsizeftlbways; struct cache_desc icache; /* Primary I-cache */ struct cache_desc dcache; /* Primary D or combined I/D cache */ + struct cache_desc vcache; /* Victim cache, between pcache and scache */ struct cache_desc scache; /* Secondary cache */ struct cache_desc tcache; /* Tertiary/split secondary cache */ int srsets; /* Shadow register sets */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 9127a583d1f1..810536b6900c 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -42,6 +42,7 @@ #define PRID_COMP_LEXRA 0x0b0000 #define PRID_COMP_NETLOGIC 0x0c0000 #define PRID_COMP_CAVIUM 0x0d0000 +#define PRID_COMP_LOONGSON 0x140000 #define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */ #define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */ #define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */ @@ -241,9 +242,10 @@ #define PRID_REV_LOONGSON1B 0x0020 #define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2F 0x0003 -#define PRID_REV_LOONGSON3A 0x0005 +#define PRID_REV_LOONGSON3A_R1 0x0005 #define PRID_REV_LOONGSON3B_R1 0x0006 #define PRID_REV_LOONGSON3B_R2 0x0007 +#define PRID_REV_LOONGSON3A_R2 0x0008 /* * Older processors used to encode processor version and revision in two diff --git a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h index 98963c2c7be4..89328a3d44d8 100644 --- a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h @@ -16,11 +16,6 @@ #ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H #define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H -#define cpu_dcache_line_size() 32 -#define cpu_icache_line_size() 32 -#define cpu_scache_line_size() 32 - - #define cpu_has_32fpr 1 #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 @@ -31,24 +26,17 @@ #define cpu_has_counter 1 #define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) #define cpu_has_divec 0 -#define cpu_has_dsp 0 -#define cpu_has_dsp2 0 #define cpu_has_ejtag 0 -#define cpu_has_ic_fills_f_dc 0 #define cpu_has_inclusive_pcaches 1 #define cpu_has_llsc 1 #define cpu_has_mcheck 0 #define cpu_has_mdmx 0 #define cpu_has_mips16 0 -#define cpu_has_mips32r2 0 #define cpu_has_mips3d 0 -#define cpu_has_mips64r2 0 #define cpu_has_mipsmt 0 -#define cpu_has_prefetch 0 #define cpu_has_smartmips 0 #define cpu_has_tlb 1 #define cpu_has_tx39_cache 0 -#define cpu_has_userlocal 0 #define cpu_has_vce 0 #define cpu_has_veic 0 #define cpu_has_vint 0 @@ -56,6 +44,10 @@ #define cpu_has_watch 1 #define cpu_has_local_ebase 0 -#define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3) +#ifdef CONFIG_CPU_LOONGSON3 +#define cpu_has_wsbh 1 +#define cpu_has_ic_fills_f_dc 1 +#define cpu_hwrena_impl_bits 0xc0000000 +#endif #endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index 3f2f84f6c401..da83482ff0b9 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -23,7 +23,8 @@ or t0, (0x1 << 7) mtc0 t0, $16, 3 /* Set ELPA on LOONGSON3 pagegrain */ - li t0, (0x1 << 29) + mfc0 t0, $5, 1 + or t0, (0x1 << 29) mtc0 t0, $5, 1 _ehb .set pop @@ -42,7 +43,8 @@ or t0, (0x1 << 7) mtc0 t0, $16, 3 /* Set ELPA on LOONGSON3 pagegrain */ - li t0, (0x1 << 29) + mfc0 t0, $5, 1 + or t0, (0x1 << 29) mtc0 t0, $5, 1 _ehb .set pop diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index aea90631a301..28ded49d25c6 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -636,6 +636,8 @@ #define MIPS_CONF6_SYND (_ULCAST_(1) << 13) /* proAptiv FTLB on/off bit */ #define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15) +/* Loongson-3 FTLB on/off bit */ +#define MIPS_CONF6_FTLBDIS (_ULCAST_(1) << 22) /* FTLB probability bits */ #define MIPS_CONF6_FTLBP_SHIFT (16) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 45de57651619..7f422500b65d 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -384,7 +384,7 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pte_val(pte) & _PAGE_NO_READ)) pte_val(pte) |= _PAGE_SILENT_READ; else @@ -570,7 +570,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) { pmd_val(pmd) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pmd_val(pmd) & _PAGE_NO_READ)) pmd_val(pmd) |= _PAGE_SILENT_READ; else diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index d72bd7eb8bce..2bfd48375b46 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -562,6 +562,16 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) write_c0_config7(config | (calculate_ftlb_probability(c) << MIPS_CONF7_FTLBP_SHIFT)); break; + case CPU_LOONGSON3: + /* Loongson-3 cores use Config6 to enable the FTLB */ + config = read_c0_config6(); + if (enable) + /* Enable FTLB */ + write_c0_config6(config & ~MIPS_CONF6_FTLBDIS); + else + /* Disable FTLB */ + write_c0_config6(config | MIPS_CONF6_FTLBDIS); + break; default: return 1; } @@ -1178,7 +1188,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) set_isa(c, MIPS_CPU_ISA_III); c->fpu_msk31 |= FPU_CSR_CONDX; break; - case PRID_REV_LOONGSON3A: + case PRID_REV_LOONGSON3A_R1: c->cputype = CPU_LOONGSON3; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); @@ -1512,6 +1522,29 @@ platform: } } +static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) +{ + switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON3A_R2: + c->cputype = CPU_LOONGSON3; + __cpu_name[cpu] = "ICT Loongson-3"; + set_elf_platform(cpu, "loongson3a"); + set_isa(c, MIPS_CPU_ISA_M64R2); + break; + } + + decode_configs(c); + c->options |= MIPS_CPU_TLBINV; + c->writecombine = _CACHE_UNCACHED_ACCELERATED; + break; + default: + panic("Unknown Loongson Processor ID!"); + break; + } +} + static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) { decode_configs(c); @@ -1659,6 +1692,9 @@ void cpu_probe(void) case PRID_COMP_CAVIUM: cpu_probe_cavium(c, cpu); break; + case PRID_COMP_LOONGSON: + cpu_probe_loongson(c, cpu); + break; case PRID_COMP_INGENIC_D0: case PRID_COMP_INGENIC_D1: case PRID_COMP_INGENIC_E1: diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 46794d64c0bf..60ab4c44d305 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -181,6 +181,11 @@ void __init check_wait(void) case CPU_XLP: cpu_wait = r4k_wait; break; + case CPU_LOONGSON3: + if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2) + cpu_wait = r4k_wait; + break; + case CPU_BMIPS5000: cpu_wait = r4k_wait_irqoff; break; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index dcda63e65854..38864dc179ff 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1772,7 +1772,8 @@ asmlinkage void do_ftlb(void) /* For the moment, report the problem and hang. */ if ((cpu_has_mips_r2_r6) && - ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { + (((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) || + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_LOONGSON))) { pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", read_c0_ecc()); pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index d6d07ad56180..57d590ac8004 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c @@ -105,6 +105,10 @@ void __init prom_init_env(void) loongson_chiptemp[1] = 0x900010001fe0019c; loongson_chiptemp[2] = 0x900020001fe0019c; loongson_chiptemp[3] = 0x900030001fe0019c; + loongson_freqctrl[0] = 0x900000001fe001d0; + loongson_freqctrl[1] = 0x900010001fe001d0; + loongson_freqctrl[2] = 0x900020001fe001d0; + loongson_freqctrl[3] = 0x900030001fe001d0; loongson_sysconf.ht_control_base = 0x90000EFDFB000000; loongson_sysconf.workarounds = WORKAROUND_CPUFREQ; } else if (ecpu->cputype == Loongson_3B) { @@ -187,7 +191,8 @@ void __init prom_init_env(void) case PRID_REV_LOONGSON2F: cpu_clock_freq = 797000000; break; - case PRID_REV_LOONGSON3A: + case PRID_REV_LOONGSON3A_R1: + case PRID_REV_LOONGSON3A_R2: cpu_clock_freq = 900000000; break; case PRID_REV_LOONGSON3B_R1: diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index b913cd240d77..e59759af63d9 100644 --- a/arch/mips/loongson64/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c @@ -439,7 +439,7 @@ static void loongson3_cpu_die(unsigned int cpu) * flush all L1 entries at first. Then, another core (usually Core 0) can * safely disable the clock of the target core. loongson3_play_dead() is * called via CKSEG1 (uncached and unmmaped) */ -static void loongson3a_play_dead(int *state_addr) +static void loongson3a_r1_play_dead(int *state_addr) { register int val; register long cpuid, core, node, count; @@ -501,6 +501,89 @@ static void loongson3a_play_dead(int *state_addr) : "a1"); } +static void loongson3a_r2_play_dead(int *state_addr) +{ + register int val; + register long cpuid, core, node, count; + register void *addr, *base, *initfunc; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " li %[addr], 0x80000000 \n" /* KSEG0 */ + "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ + " cache 0, 1(%[addr]) \n" + " cache 0, 2(%[addr]) \n" + " cache 0, 3(%[addr]) \n" + " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ + " cache 1, 1(%[addr]) \n" + " cache 1, 2(%[addr]) \n" + " cache 1, 3(%[addr]) \n" + " addiu %[sets], %[sets], -1 \n" + " bnez %[sets], 1b \n" + " addiu %[addr], %[addr], 0x40 \n" + " li %[addr], 0x80000000 \n" /* KSEG0 */ + "2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */ + " cache 2, 1(%[addr]) \n" + " cache 2, 2(%[addr]) \n" + " cache 2, 3(%[addr]) \n" + " cache 2, 4(%[addr]) \n" + " cache 2, 5(%[addr]) \n" + " cache 2, 6(%[addr]) \n" + " cache 2, 7(%[addr]) \n" + " cache 2, 8(%[addr]) \n" + " cache 2, 9(%[addr]) \n" + " cache 2, 10(%[addr]) \n" + " cache 2, 11(%[addr]) \n" + " cache 2, 12(%[addr]) \n" + " cache 2, 13(%[addr]) \n" + " cache 2, 14(%[addr]) \n" + " cache 2, 15(%[addr]) \n" + " addiu %[vsets], %[vsets], -1 \n" + " bnez %[vsets], 2b \n" + " addiu %[addr], %[addr], 0x40 \n" + " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ + " sw %[val], (%[state_addr]) \n" + " sync \n" + " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ + " .set pop \n" + : [addr] "=&r" (addr), [val] "=&r" (val) + : [state_addr] "r" (state_addr), + [sets] "r" (cpu_data[smp_processor_id()].dcache.sets), + [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets)); + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips64 \n" + " mfc0 %[cpuid], $15, 1 \n" + " andi %[cpuid], 0x3ff \n" + " dli %[base], 0x900000003ff01000 \n" + " andi %[core], %[cpuid], 0x3 \n" + " sll %[core], 8 \n" /* get core id */ + " or %[base], %[base], %[core] \n" + " andi %[node], %[cpuid], 0xc \n" + " dsll %[node], 42 \n" /* get node id */ + " or %[base], %[base], %[node] \n" + "1: li %[count], 0x100 \n" /* wait for init loop */ + "2: bnez %[count], 2b \n" /* limit mailbox access */ + " addiu %[count], -1 \n" + " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ + " beqz %[initfunc], 1b \n" + " nop \n" + " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ + " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ + " ld $a1, 0x38(%[base]) \n" + " jr %[initfunc] \n" /* jump to initial PC */ + " nop \n" + " .set pop \n" + : [core] "=&r" (core), [node] "=&r" (node), + [base] "=&r" (base), [cpuid] "=&r" (cpuid), + [count] "=&r" (count), [initfunc] "=&r" (initfunc) + : /* No Input */ + : "a1"); +} + static void loongson3b_play_dead(int *state_addr) { register int val; @@ -572,13 +655,18 @@ void play_dead(void) void (*play_dead_at_ckseg1)(int *); idle_task_exit(); - switch (loongson_sysconf.cputype) { - case Loongson_3A: + switch (read_c0_prid() & PRID_REV_MASK) { + case PRID_REV_LOONGSON3A_R1: default: play_dead_at_ckseg1 = - (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead); + (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead); + break; + case PRID_REV_LOONGSON3A_R2: + play_dead_at_ckseg1 = + (void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead); break; - case Loongson_3B: + case PRID_REV_LOONGSON3B_R1: + case PRID_REV_LOONGSON3B_R2: play_dead_at_ckseg1 = (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead); break; @@ -593,9 +681,9 @@ void loongson3_disable_clock(int cpu) uint64_t core_id = cpu_data[cpu].core; uint64_t package_id = cpu_data[cpu].package; - if (loongson_sysconf.cputype == Loongson_3A) { + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) { LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); - } else if (loongson_sysconf.cputype == Loongson_3B) { + } else { if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); } @@ -606,9 +694,9 @@ void loongson3_enable_clock(int cpu) uint64_t core_id = cpu_data[cpu].core; uint64_t package_id = cpu_data[cpu].package; - if (loongson_sysconf.cputype == Loongson_3A) { + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) { LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); - } else if (loongson_sysconf.cputype == Loongson_3B) { + } else { if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 6f43bdf9a679..77fbaf1cdfd6 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -77,6 +77,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) */ static unsigned long icache_size __read_mostly; static unsigned long dcache_size __read_mostly; +static unsigned long vcache_size __read_mostly; static unsigned long scache_size __read_mostly; /* @@ -1349,6 +1350,31 @@ static void probe_pcache(void) c->dcache.linesz); } +static void probe_vcache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config2, lsize; + + if (current_cpu_type() != CPU_LOONGSON3) + return; + + config2 = read_c0_config2(); + if ((lsize = ((config2 >> 20) & 15))) + c->vcache.linesz = 2 << lsize; + else + c->vcache.linesz = lsize; + + c->vcache.sets = 64 << ((config2 >> 24) & 15); + c->vcache.ways = 1 + ((config2 >> 16) & 15); + + vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz; + + c->vcache.waybit = 0; + + pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n", + vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz); +} + /* * If you even _breathe_ on this function, look at the gcc output and make sure * it does not pop things on and off the stack for the cache sizing loop that @@ -1671,6 +1697,7 @@ void r4k_cache_init(void) struct cpuinfo_mips *c = ¤t_cpu_data; probe_pcache(); + probe_vcache(); setup_scache(); r4k_blast_dcache_page_setup(); diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c index 0f6c63e17049..8c5072b7ad4f 100644 --- a/drivers/platform/mips/cpu_hwmon.c +++ b/drivers/platform/mips/cpu_hwmon.c @@ -20,9 +20,9 @@ int loongson3_cpu_temp(int cpu) u32 reg; reg = LOONGSON_CHIPTEMP(cpu); - if (loongson_sysconf.cputype == Loongson_3A) + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) reg = (reg >> 8) & 0xff; - else if (loongson_sysconf.cputype == Loongson_3B) + else reg = ((reg >> 8) & 0xff) - 100; return (int)reg * 1000; -- cgit v1.2.3-59-g8ed1b From 37fbe8faa94fa8cae889a3a793fd7b32508b26ab Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:10 +0800 Subject: MIPS: Loongson-3: Set cache flush handlers to cache_noop Loongson-3 maintains cache coherency by hardware, this means: 1) It's icache is coherent with dcache. 2) It's dcaches don't alias (maybe depend on PAGE_SIZE). 3) It maintains cache coherency across cores (and for DMA). So we can skip most cache flush operations by setting relevant handlers to `cache_noop' in `r4k_cache_init'. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12752/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 77fbaf1cdfd6..3415d3e2a63b 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1796,6 +1796,20 @@ void r4k_cache_init(void) /* Optimization: an L2 flush implicitly flushes the L1 */ current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES; break; + case CPU_LOONGSON3: + /* Loongson-3 maintains cache coherency by hardware */ + __flush_cache_all = cache_noop; + __flush_cache_vmap = cache_noop; + __flush_cache_vunmap = cache_noop; + __flush_kernel_vmap_range = (void *)cache_noop; + flush_cache_mm = (void *)cache_noop; + flush_cache_page = (void *)cache_noop; + flush_cache_range = (void *)cache_noop; + flush_cache_sigtramp = (void *)cache_noop; + flush_icache_all = (void *)cache_noop; + flush_data_cache_page = (void *)cache_noop; + local_flush_data_cache_page = (void *)cache_noop; + break; } } -- cgit v1.2.3-59-g8ed1b From 06e4814eec988f7ee01c29762f945b3ff59355fb Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:11 +0800 Subject: MIPS: Loongson: Invalidate special TLBs when needed Loongson-2 has a 4 entry itlb which is a subset of jtlb, Loongson-3 has a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. We should write diag register to invalidate itlb/dtlb when flushing jtlb because itlb/dtlb are not totally transparent to software. For Loongson-3A R2 (and newer), we should invalidate ITLB, DTLB, VTLB and FTLB before we enable/disable FTLB. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12753/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 9 +++++++++ arch/mips/kernel/cpu-probe.c | 3 +++ arch/mips/mm/tlb-r4k.c | 27 +++++++++++++++------------ 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 28ded49d25c6..0d0bd161fc10 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -780,6 +780,15 @@ /* Disable Branch Return Cache */ #define R10K_DIAG_D_BRC (_ULCAST_(1) << 22) +/* Flush ITLB */ +#define LOONGSON_DIAG_ITLB (_ULCAST_(1) << 2) +/* Flush DTLB */ +#define LOONGSON_DIAG_DTLB (_ULCAST_(1) << 3) +/* Flush VTLB */ +#define LOONGSON_DIAG_VTLB (_ULCAST_(1) << 12) +/* Flush FTLB */ +#define LOONGSON_DIAG_FTLB (_ULCAST_(1) << 13) + /* * Coprocessor 1 (FPU) register names */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 2bfd48375b46..515dd1f8901e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -563,6 +563,9 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) << MIPS_CONF7_FTLBP_SHIFT)); break; case CPU_LOONGSON3: + /* Flush ITLB, DTLB, VTLB and FTLB */ + write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB | + LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB); /* Loongson-3 cores use Config6 to enable the FTLB */ config = read_c0_config6(); if (enable) diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index c17d7627f872..4c3362b46066 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -28,25 +28,28 @@ extern void build_tlb_refill_handler(void); /* - * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, - * unfortunately, itlb is not totally transparent to software. + * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has + * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately, + * itlb/dtlb are not totally transparent to software. */ -static inline void flush_itlb(void) +static inline void flush_micro_tlb(void) { switch (current_cpu_type()) { case CPU_LOONGSON2: + write_c0_diag(LOONGSON_DIAG_ITLB); + break; case CPU_LOONGSON3: - write_c0_diag(4); + write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); break; default: break; } } -static inline void flush_itlb_vm(struct vm_area_struct *vma) +static inline void flush_micro_tlb_vm(struct vm_area_struct *vma) { if (vma->vm_flags & VM_EXEC) - flush_itlb(); + flush_micro_tlb(); } void local_flush_tlb_all(void) @@ -93,7 +96,7 @@ void local_flush_tlb_all(void) tlbw_use_hazard(); write_c0_entryhi(old_ctx); htw_start(); - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } EXPORT_SYMBOL(local_flush_tlb_all); @@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, } else { drop_mmu_context(mm, cpu); } - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } } @@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) } else { local_flush_tlb_all(); } - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } @@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) finish: write_c0_entryhi(oldpid); htw_start(); - flush_itlb_vm(vma); + flush_micro_tlb_vm(vma); local_irq_restore(flags); } } @@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long page) } write_c0_entryhi(oldpid); htw_start(); - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } @@ -357,7 +360,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) } tlbw_use_hazard(); htw_start(); - flush_itlb_vm(vma); + flush_micro_tlb_vm(vma); local_irq_restore(flags); } -- cgit v1.2.3-59-g8ed1b From 380cd582c08831217ae693c86411902e6300ba6b Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:12 +0800 Subject: MIPS: Loongson-3: Fast TLB refill handler Loongson-3A R2 has pwbase/pwfield/pwsize/pwctl registers in CP0 (this is very similar to HTW) and lwdir/lwpte/lddir/ldpte instructions which can be used for fast TLB refill. [ralf@linux-mips.org: Resolve conflict.] Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12754/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 3 + arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 6 ++ arch/mips/include/asm/uasm.h | 3 +- arch/mips/include/uapi/asm/inst.h | 10 +++ arch/mips/kernel/cpu-probe.c | 2 +- arch/mips/mm/tlbex.c | 124 ++++++++++++++++++++++++++++++++++- arch/mips/mm/uasm-mips.c | 2 + arch/mips/mm/uasm.c | 3 + 9 files changed, 149 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 6ff0504d090d..da92d513a395 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -35,6 +35,9 @@ #ifndef cpu_has_htw #define cpu_has_htw (cpu_data[0].options & MIPS_CPU_HTW) #endif +#ifndef cpu_has_ldpte +#define cpu_has_ldpte (cpu_data[0].options & MIPS_CPU_LDPTE) +#endif #ifndef cpu_has_rixiex #define cpu_has_rixiex (cpu_data[0].options & MIPS_CPU_RIXIEX) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 810536b6900c..d9150a210df6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -402,6 +402,7 @@ enum cpu_type_enum { #define MIPS_CPU_NAN_LEGACY MBIT_ULL(38) /* Legacy NaN implemented */ #define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ +#define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 0d0bd161fc10..1e9d337fb077 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1474,6 +1474,12 @@ do { \ #define read_c0_pwctl() __read_32bit_c0_register($6, 6) #define write_c0_pwctl(val) __write_32bit_c0_register($6, 6, val) +#define read_c0_pgd() __read_64bit_c0_register($9, 7) +#define write_c0_pgd(val) __write_64bit_c0_register($9, 7, val) + +#define read_c0_kpgd() __read_64bit_c0_register($31, 7) +#define write_c0_kpgd(val) __write_64bit_c0_register($31, 7, val) + /* Cavium OCTEON (cnMIPS) */ #define read_c0_cvmcount() __read_ulong_c0_register($9, 6) #define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val) diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index fc1cdd25fcda..b6ecfeee4dbe 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -171,7 +171,8 @@ Ip_u2u1(_wsbh); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); Ip_u2u1(_yield); - +Ip_u1u2(_ldpte); +Ip_u2u1u3(_lddir); /* Handle labels. */ struct uasm_label { diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index ddea53e3a9bb..3bb8cd957e81 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -203,6 +203,16 @@ enum mad_func { nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e }; +/* + * func field for page table walker (Loongson-3). + */ +enum ptw_func { + lwdir_op = 0x00, + lwpte_op = 0x01, + lddir_op = 0x02, + ldpte_op = 0x03, +}; + /* * func field for special3 lx opcodes (Cavium Octeon). */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 515dd1f8901e..064ab389e964 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1539,7 +1539,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) } decode_configs(c); - c->options |= MIPS_CPU_TLBINV; + c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; c->writecombine = _CACHE_UNCACHED_ACCELERATED; break; default: diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 84c6e3fda84a..7153e1fb0cd4 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -284,7 +284,12 @@ static inline void dump_handler(const char *symbol, const u32 *handler, int coun #define C0_ENTRYLO1 3, 0 #define C0_CONTEXT 4, 0 #define C0_PAGEMASK 5, 0 +#define C0_PWBASE 5, 5 +#define C0_PWFIELD 5, 6 +#define C0_PWSIZE 5, 7 +#define C0_PWCTL 6, 6 #define C0_BADVADDR 8, 0 +#define C0_PGD 9, 7 #define C0_ENTRYHI 10, 0 #define C0_EPC 14, 0 #define C0_XCONTEXT 20, 0 @@ -808,7 +813,10 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, if (pgd_reg != -1) { /* pgd is in pgd_reg */ - UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); + if (cpu_has_ldpte) + UASM_i_MFC0(p, ptr, C0_PWBASE); + else + UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); } else { #if defined(CONFIG_MIPS_PGD_C0_CONTEXT) /* @@ -1421,6 +1429,108 @@ static void build_r4000_tlb_refill_handler(void) dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); } +static void setup_pw(void) +{ + unsigned long pgd_i, pgd_w; +#ifndef __PAGETABLE_PMD_FOLDED + unsigned long pmd_i, pmd_w; +#endif + unsigned long pt_i, pt_w; + unsigned long pte_i, pte_w; +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + unsigned long psn; + + psn = ilog2(_PAGE_HUGE); /* bit used to indicate huge page */ +#endif + pgd_i = PGDIR_SHIFT; /* 1st level PGD */ +#ifndef __PAGETABLE_PMD_FOLDED + pgd_w = PGDIR_SHIFT - PMD_SHIFT + PGD_ORDER; + + pmd_i = PMD_SHIFT; /* 2nd level PMD */ + pmd_w = PMD_SHIFT - PAGE_SHIFT; +#else + pgd_w = PGDIR_SHIFT - PAGE_SHIFT + PGD_ORDER; +#endif + + pt_i = PAGE_SHIFT; /* 3rd level PTE */ + pt_w = PAGE_SHIFT - 3; + + pte_i = ilog2(_PAGE_GLOBAL); + pte_w = 0; + +#ifndef __PAGETABLE_PMD_FOLDED + write_c0_pwfield(pgd_i << 24 | pmd_i << 12 | pt_i << 6 | pte_i); + write_c0_pwsize(1 << 30 | pgd_w << 24 | pmd_w << 12 | pt_w << 6 | pte_w); +#else + write_c0_pwfield(pgd_i << 24 | pt_i << 6 | pte_i); + write_c0_pwsize(1 << 30 | pgd_w << 24 | pt_w << 6 | pte_w); +#endif + +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + write_c0_pwctl(1 << 6 | psn); +#endif + write_c0_kpgd(swapper_pg_dir); + kscratch_used_mask |= (1 << 7); /* KScratch6 is used for KPGD */ +} + +static void build_loongson3_tlb_refill_handler(void) +{ + u32 *p = tlb_handler; + struct uasm_label *l = labels; + struct uasm_reloc *r = relocs; + + memset(labels, 0, sizeof(labels)); + memset(relocs, 0, sizeof(relocs)); + memset(tlb_handler, 0, sizeof(tlb_handler)); + + if (check_for_high_segbits) { + uasm_i_dmfc0(&p, K0, C0_BADVADDR); + uasm_i_dsrl_safe(&p, K1, K0, PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); + uasm_il_beqz(&p, &r, K1, label_vmalloc); + uasm_i_nop(&p); + + uasm_il_bgez(&p, &r, K0, label_large_segbits_fault); + uasm_i_nop(&p); + uasm_l_vmalloc(&l, p); + } + + uasm_i_dmfc0(&p, K1, C0_PGD); + + uasm_i_lddir(&p, K0, K1, 3); /* global page dir */ +#ifndef __PAGETABLE_PMD_FOLDED + uasm_i_lddir(&p, K1, K0, 1); /* middle page dir */ +#endif + uasm_i_ldpte(&p, K1, 0); /* even */ + uasm_i_ldpte(&p, K1, 1); /* odd */ + uasm_i_tlbwr(&p); + + /* restore page mask */ + if (PM_DEFAULT_MASK >> 16) { + uasm_i_lui(&p, K0, PM_DEFAULT_MASK >> 16); + uasm_i_ori(&p, K0, K0, PM_DEFAULT_MASK & 0xffff); + uasm_i_mtc0(&p, K0, C0_PAGEMASK); + } else if (PM_DEFAULT_MASK) { + uasm_i_ori(&p, K0, 0, PM_DEFAULT_MASK); + uasm_i_mtc0(&p, K0, C0_PAGEMASK); + } else { + uasm_i_mtc0(&p, 0, C0_PAGEMASK); + } + + uasm_i_eret(&p); + + if (check_for_high_segbits) { + uasm_l_large_segbits_fault(&l, p); + UASM_i_LA(&p, K1, (unsigned long)tlb_do_page_fault_0); + uasm_i_jr(&p, K1); + uasm_i_nop(&p); + } + + uasm_resolve_relocs(relocs, labels); + memcpy((void *)(ebase + 0x80), tlb_handler, 0x80); + local_flush_icache_range(ebase + 0x80, ebase + 0x100); + dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32); +} + extern u32 handle_tlbl[], handle_tlbl_end[]; extern u32 handle_tlbs[], handle_tlbs_end[]; extern u32 handle_tlbm[], handle_tlbm_end[]; @@ -1468,7 +1578,10 @@ static void build_setup_pgd(void) } else { /* PGD in c0_KScratch */ uasm_i_jr(&p, 31); - UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); + if (cpu_has_ldpte) + UASM_i_MTC0(&p, a0, C0_PWBASE); + else + UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); } #else #ifdef CONFIG_SMP @@ -2437,13 +2550,18 @@ void build_tlb_refill_handler(void) break; default: + if (cpu_has_ldpte) + setup_pw(); + if (!run_once) { scratch_reg = allocate_kscratch(); build_setup_pgd(); build_r4000_tlb_load_handler(); build_r4000_tlb_store_handler(); build_r4000_tlb_modify_handler(); - if (!cpu_has_local_ebase) + if (cpu_has_ldpte) + build_loongson3_tlb_refill_handler(); + else if (!cpu_has_local_ebase) build_r4000_tlb_refill_handler(); flush_tlb_handlers(); run_once++; diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index b4a837893562..9c2220a45189 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -153,6 +153,8 @@ static struct insn insn_table[] = { { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD }, + { insn_ldpte, M(lwc2_op, 0, 0, 0, ldpte_op, mult_op), RS | RD }, + { insn_lddir, M(lwc2_op, 0, 0, 0, lddir_op, mult_op), RS | RT | RD }, { insn_invalid, 0, 0 } }; diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 319051c34343..ad718debc35a 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -60,6 +60,7 @@ enum opcode { insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield, + insn_lddir, insn_ldpte, }; struct insn { @@ -335,6 +336,8 @@ I_u1u2s3(_bbit0); I_u1u2s3(_bbit1); I_u3u1u2(_lwx) I_u3u1u2(_ldx) +I_u1u2(_ldpte) +I_u2u1u3(_lddir) #ifdef CONFIG_CPU_CAVIUM_OCTEON #include -- cgit v1.2.3-59-g8ed1b From 1e820da3c9af4f5771d2ad47099919429b906ac6 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:13 +0800 Subject: MIPS: Loongson-3: Introduce CONFIG_LOONGSON3_ENHANCEMENT New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer), Fast TLB refill support, etc. This patch introduce a config option, CONFIG_LOONGSON3_ENHANCEMENT, to enable those enhancements which are not probed at run time. If you want a generic kernel to run on all Loongson 3 machines, please say 'N' here. If you want a high-performance kernel to run on new Loongson 3 machines only, please say 'Y' here. Some additional explanations: 1) SFB locates between core and L1 cache, it causes memory access out of order, so writel/outl (and other similar functions) need a I/O reorder barrier. 2) Loongson 3 has a bug that di instruction can not save the irqflag, so arch_local_irq_save() is modified. Since CPU_MIPSR2 is selected by CONFIG_LOONGSON3_ENHANCEMENT, generic kernel doesn't use ei/di at all. 3) CPU_HAS_PREFETCH is selected by CONFIG_LOONGSON3_ENHANCEMENT, so MIPS_CPU_PREFETCH (used by uasm) probing is also put in this patch. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12755/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 18 ++++++++++++++++++ arch/mips/include/asm/hazards.h | 7 ++++--- arch/mips/include/asm/io.h | 10 +++++----- arch/mips/include/asm/irqflags.h | 5 +++++ .../include/asm/mach-loongson64/kernel-entry-init.h | 12 ++++++++++++ arch/mips/mm/c-r4k.c | 2 ++ arch/mips/mm/page.c | 9 +++++++++ 7 files changed, 55 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index adcc97ea4392..d5c3621f0dd1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1360,6 +1360,24 @@ config CPU_LOONGSON3 The Loongson 3 processor implements the MIPS64R2 instruction set with many extensions. +config LOONGSON3_ENHANCEMENT + bool "New Loongson 3 CPU Enhancements" + default n + select CPU_MIPSR2 + select CPU_HAS_PREFETCH + depends on CPU_LOONGSON3 + help + New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A + R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as + FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User + Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer), + Fast TLB refill support, etc. + + This option enable those enhancements which are not probed at run + time. If you want a generic kernel to run on all Loongson 3 machines, + please say 'N' here. If you want a high-performance kernel to run on + new Loongson 3 machines only, please say 'Y' here. + config CPU_LOONGSON2E bool "Loongson 2E" depends on SYS_HAS_CPU_LOONGSON2E diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 7b99efd31074..dbb1eb6e284f 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -22,7 +22,8 @@ /* * TLB hazards */ -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON) +#if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)) && \ + !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_LOONGSON3_ENHANCEMENT) /* * MIPSR2 defines ehb for hazard avoidance @@ -155,8 +156,8 @@ do { \ } while (0) #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ - defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \ - defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR) + defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \ + defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR) /* * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 2b4dc7ad53b8..ecabc00c1e66 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -304,10 +304,10 @@ static inline void iounmap(const volatile void __iomem *addr) #undef __IS_KSEG1 } -#ifdef CONFIG_CPU_CAVIUM_OCTEON -#define war_octeon_io_reorder_wmb() wmb() +#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT) +#define war_io_reorder_wmb() wmb() #else -#define war_octeon_io_reorder_wmb() do { } while (0) +#define war_io_reorder_wmb() do { } while (0) #endif #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ @@ -318,7 +318,7 @@ static inline void pfx##write##bwlq(type val, \ volatile type *__mem; \ type __val; \ \ - war_octeon_io_reorder_wmb(); \ + war_io_reorder_wmb(); \ \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ \ @@ -387,7 +387,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ volatile type *__addr; \ type __val; \ \ - war_octeon_io_reorder_wmb(); \ + war_io_reorder_wmb(); \ \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 65c351e328cc..9d3610be2323 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -41,7 +41,12 @@ static inline unsigned long arch_local_irq_save(void) " .set push \n" " .set reorder \n" " .set noat \n" +#if defined(CONFIG_CPU_LOONGSON3) + " mfc0 %[flags], $12 \n" + " di \n" +#else " di %[flags] \n" +#endif " andi %[flags], 1 \n" " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index da83482ff0b9..8393bc548987 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -26,6 +26,12 @@ mfc0 t0, $5, 1 or t0, (0x1 << 29) mtc0 t0, $5, 1 +#ifdef CONFIG_LOONGSON3_ENHANCEMENT + /* Enable STFill Buffer */ + mfc0 t0, $16, 6 + or t0, 0x100 + mtc0 t0, $16, 6 +#endif _ehb .set pop #endif @@ -46,6 +52,12 @@ mfc0 t0, $5, 1 or t0, (0x1 << 29) mtc0 t0, $5, 1 +#ifdef CONFIG_LOONGSON3_ENHANCEMENT + /* Enable STFill Buffer */ + mfc0 t0, $16, 6 + or t0, 0x100 + mtc0 t0, $16, 6 +#endif _ehb .set pop #endif diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 3415d3e2a63b..d73b304cfe8a 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1161,6 +1161,8 @@ static void probe_pcache(void) c->dcache.ways * c->dcache.linesz; c->dcache.waybit = 0; + if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2) + c->options |= MIPS_CPU_PREFETCH; break; case CPU_CAVIUM_OCTEON3: diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 885d73ffd6fb..c41953ca6605 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -188,6 +188,15 @@ static void set_prefetch_parameters(void) } break; + case CPU_LOONGSON3: + /* Loongson-3 only support the Pref_Load/Pref_Store. */ + pref_bias_clear_store = 128; + pref_bias_copy_load = 128; + pref_bias_copy_store = 128; + pref_src_mode = Pref_Load; + pref_dst_mode = Pref_Store; + break; + default: pref_bias_clear_store = 128; pref_bias_copy_load = 256; -- cgit v1.2.3-59-g8ed1b From 201233e6b5d8c7adb84e3a718b0cb33f3665fb7c Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 4 Dec 2015 19:41:12 +0800 Subject: MIPS: traps: remove unused variable flags is indeed unused. Signed-off-by: Tony Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11699/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 38864dc179ff..f586b8b23f60 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1353,7 +1353,6 @@ asmlinkage void do_cpu(struct pt_regs *regs) unsigned long fcr31; unsigned int cpid; int status, err; - unsigned long __maybe_unused flags; int sig; prev_state = exception_enter(); -- cgit v1.2.3-59-g8ed1b From cb80b2a38bd609b2f5a650e9ab87ea50105ad5ea Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 19 Nov 2015 17:38:21 -0800 Subject: MIPS: remove aliasing alignment if HW has antialising support MIPS hardware may have an antialising support and it works even page size is small. Setup a shared memory aliasing mask to page size if hardware has an antialising support. Big shared memory mask forces a disruption in page address assignment and that corrupts Android library memory handling. Signed-off-by: Leonid Yegoshin Cc: cernekee@gmail.com Cc: paul.gortmaker@windriver.com Cc: kumba@gentoo.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11516/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index d73b304cfe8a..ef7f925dd1b0 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1721,7 +1721,7 @@ void r4k_cache_init(void) * This code supports virtually indexed processors and will be * unnecessarily inefficient on physically indexed processors. */ - if (c->dcache.linesz) + if (c->dcache.linesz && cpu_has_dc_aliases) shm_align_mask = max_t( unsigned long, c->dcache.sets * c->dcache.linesz - 1, PAGE_SIZE - 1); -- cgit v1.2.3-59-g8ed1b From 7939469da29a8dfa3947e5d9648d0f0501bc4ba0 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Mon, 19 Oct 2015 11:39:55 -0700 Subject: MIPS64: signal: Fix o32 sigaction syscall MIPS32 o32 ABI sigaction() processing on MIPS64 n64 kernel was incorrectly set to processing aka rt_sigaction() variant only. Signed-off-by: Leonid Yegoshin Cc: paul.burton@imgtec.com Cc: richard@nod.at Cc: luto@amacapital.net Cc: alex.smith@imgtec.com Cc: Maciej W. Rozycki Cc: mpe@ellerman.id.au Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11321/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/signal.h | 12 +++++++++--- arch/mips/kernel/signal.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h index 003e273eff4c..2292373ff11a 100644 --- a/arch/mips/include/asm/signal.h +++ b/arch/mips/include/asm/signal.h @@ -11,11 +11,17 @@ #include +#ifdef CONFIG_MIPS32_COMPAT +extern struct mips_abi mips_abi_32; -#ifdef CONFIG_TRAD_SIGNALS -#define sig_uses_siginfo(ka) ((ka)->sa.sa_flags & SA_SIGINFO) +#define sig_uses_siginfo(ka, abi) \ + ((abi != &mips_abi_32) ? 1 : \ + ((ka)->sa.sa_flags & SA_SIGINFO)) #else -#define sig_uses_siginfo(ka) (1) +#define sig_uses_siginfo(ka, abi) \ + (config_enabled(CONFIG_64BIT) ? 1 : \ + (config_enabled(CONFIG_TRAD_SIGNALS) ? \ + ((ka)->sa.sa_flags & SA_SIGINFO) : 1) ) #endif #include diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index bf792e2839a6..5f18d0b879e0 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -798,7 +798,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->regs[0] = 0; /* Don't deal with this again. */ } - if (sig_uses_siginfo(&ksig->ka)) + if (sig_uses_siginfo(&ksig->ka, abi)) ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn, ksig, regs, oldset); else -- cgit v1.2.3-59-g8ed1b From 1e321fa917fb2d30d39ff1c6ea89d6f1cf4f34a5 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 14 May 2015 18:34:43 -0700 Subject: MIPS64: Support of at least 48 bits of SEGBITS SEGBITS is 40 bits or more, depending on CPU type. Introduces optional support for 48 bits of application virtual address space. Only 16K and 64K pages are supported. Enabling will result in a memory overhead of a small number of pages for small applications. For 64K pages a 3rd level of page tables is required which has some impact during software TLB refill. [ralf@linux-mips.org: Fixed things raised in the review of the version posted and changed kconfig to be a bit more userfriendly.] Signed-off-by: Leonid Yegoshin Cc: aleksey.makarov@auriga.com Cc: james.hogan@imgtec.com Cc: paul.burton@imgtec.com Cc: david.daney@cavium.com Cc: peterz@infradead.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: davidlohr@hp.com Cc: kirill@shutemov.name Cc: akpm@linux-foundation.org Cc: mingo@kernel.org Patchwork: https://patchwork.linux-mips.org/patch/10051/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 13 +++++++++++++ arch/mips/include/asm/pgtable-64.h | 18 +++++++++++------- arch/mips/include/asm/processor.h | 6 +++++- 3 files changed, 29 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d5c3621f0dd1..2b7af9014cce 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2076,6 +2076,16 @@ config KVM_GUEST_TIMER_FREQ emulation when determining guest CPU Frequency. Instead, the guest's timer frequency is specified directly. +config MIPS_VA_BITS_48 + bool "48 bits virtual memory" + depends on 64BIT + help + Support a maximum at least 48 bits of application virtual memory. + Default is 40 bits or less, depending on the CPU. + This option result in a small memory overhead for page tables. + This option is only supported with 16k and 64k page sizes. + If unsure, say N. + choice prompt "Kernel page size" default PAGE_SIZE_4KB @@ -2083,6 +2093,7 @@ choice config PAGE_SIZE_4KB bool "4kB" depends on !CPU_LOONGSON2 && !CPU_LOONGSON3 + depends on !MIPS_VA_BITS_48 help This option select the standard 4kB Linux page size. On some R3000-family processors this is the only available page size. Using @@ -2092,6 +2103,7 @@ config PAGE_SIZE_4KB config PAGE_SIZE_8KB bool "8kB" depends on CPU_R8000 || CPU_CAVIUM_OCTEON + depends on !MIPS_VA_BITS_48 help Using 8kB page size will result in higher performance kernel at the price of higher memory consumption. This option is available @@ -2110,6 +2122,7 @@ config PAGE_SIZE_16KB config PAGE_SIZE_32KB bool "32kB" depends on CPU_CAVIUM_OCTEON + depends on !MIPS_VA_BITS_48 help Using 32kB page size will result in higher performance kernel at the price of higher memory consumption. This option is available diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index cf661a2fb141..514cbc0a6a67 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -17,7 +17,7 @@ #include #include -#ifdef CONFIG_PAGE_SIZE_64KB +#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48) #include #else #include @@ -90,7 +90,11 @@ #define PTE_ORDER 0 #endif #ifdef CONFIG_PAGE_SIZE_16KB -#define PGD_ORDER 0 +#ifdef CONFIG_MIPS_VA_BITS_48 +#define PGD_ORDER 1 +#else +#define PGD_ORDER 0 +#endif #define PUD_ORDER aieeee_attempt_to_allocate_pud #define PMD_ORDER 0 #define PTE_ORDER 0 @@ -104,7 +108,11 @@ #ifdef CONFIG_PAGE_SIZE_64KB #define PGD_ORDER 0 #define PUD_ORDER aieeee_attempt_to_allocate_pud +#ifdef CONFIG_MIPS_VA_BITS_48 +#define PMD_ORDER 0 +#else #define PMD_ORDER aieeee_attempt_to_allocate_pmd +#endif #define PTE_ORDER 0 #endif @@ -114,11 +122,7 @@ #endif #define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) -#if PGDIR_SIZE >= TASK_SIZE64 -#define USER_PTRS_PER_PGD (1) -#else -#define USER_PTRS_PER_PGD (TASK_SIZE64 / PGDIR_SIZE) -#endif +#define USER_PTRS_PER_PGD ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1) #define FIRST_USER_ADDRESS 0UL /* diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index cfa15bad43af..7e78b6208d7d 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -63,7 +63,11 @@ extern unsigned int vced_count, vcei_count; * 8192EB ... */ #define TASK_SIZE32 0x7fff8000UL -#define TASK_SIZE64 0x10000000000UL +#ifdef CONFIG_MIPS_VA_BITS_48 +#define TASK_SIZE64 (0x1UL << ((cpu_data[0].vmbits>48)?48:cpu_data[0].vmbits)) +#else +#define TASK_SIZE64 0x10000000000UL +#endif #define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) #define STACK_TOP_MAX TASK_SIZE64 -- cgit v1.2.3-59-g8ed1b From e8b5325ca3d01c512be6f04d587869a01e0ea59f Mon Sep 17 00:00:00 2001 From: Sergey Ryazanov Date: Sat, 30 Aug 2014 06:06:28 +0400 Subject: MIPS: make PCI_DMA_BUS_IS_PHYS=1 constant No one of supported MIPS machines has an IOMMU unit, so we can safely define PCI_DMA_BUS_IS_PHYS = 1. Also remove iommu flag from the pci controller structure, since it is useless. Signed-off-by: Sergey Ryazanov Cc: Linux MIPS Patchwork: https://patchwork.linux-mips.org/patch/7604/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pci.h | 10 ++++------ arch/mips/kernel/setup.c | 7 ------- arch/mips/pci/pci-ip32.c | 1 - arch/mips/pci/pci.c | 3 --- arch/mips/pnx833x/common/setup.c | 3 --- 5 files changed, 4 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 8c16fb7b8fdb..86b239d9d75d 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -43,8 +43,6 @@ struct pci_controller { and XFree86. Eventually will be removed. */ unsigned int need_domain_info; - int iommu; - /* Optional access methods for reading/writing the bus number of the PCI controller */ int (*get_busno)(void); @@ -106,11 +104,11 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, struct pci_dev; /* - * The PCI address space does equal the physical memory address space. The - * networking and block device layers use this boolean for bounce buffer - * decisions. This is set if any hose does not have an IOMMU. + * The PCI address space does equal the physical memory address space. + * The networking and block device layers use this boolean for bounce + * buffer decisions. */ -extern unsigned int PCI_DMA_BUS_IS_PHYS; +#define PCI_DMA_BUS_IS_PHYS (1) #ifdef CONFIG_PCI_DOMAINS #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 9b20a0f89812..693e8d1a174c 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -51,13 +51,6 @@ EXPORT_SYMBOL(cpu_data); struct screen_info screen_info; #endif -/* - * Despite it's name this variable is even if we don't have PCI - */ -unsigned int PCI_DMA_BUS_IS_PHYS; - -EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); - /* * Setup information * diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c index b1e061f7fdc7..7ae89d0c7099 100644 --- a/arch/mips/pci/pci-ip32.c +++ b/arch/mips/pci/pci-ip32.c @@ -116,7 +116,6 @@ static struct pci_controller mace_pci_controller = { .pci_ops = &mace_pci_ops, .mem_resource = &mace_pci_mem_resource, .io_resource = &mace_pci_io_resource, - .iommu = 0, .mem_offset = MACE_PCI_MEM_OFFSET, .io_offset = 0, .io_map_base = CKSEG1ADDR(MACEPCI_LOW_IO), diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index b8a0bf5766f2..f1b11f0dea2d 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -83,9 +83,6 @@ static void pcibios_scanbus(struct pci_controller *hose) LIST_HEAD(resources); struct pci_bus *bus; - if (!hose->iommu) - PCI_DMA_BUS_IS_PHYS = 1; - if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY)) next_busno = (*hose->get_busno)(); diff --git a/arch/mips/pnx833x/common/setup.c b/arch/mips/pnx833x/common/setup.c index 99b4d94236cc..8a7443b2535e 100644 --- a/arch/mips/pnx833x/common/setup.c +++ b/arch/mips/pnx833x/common/setup.c @@ -38,9 +38,6 @@ extern void pnx833x_machine_power_off(void); int __init plat_mem_setup(void) { - /* fake pci bus to avoid bounce buffers */ - PCI_DMA_BUS_IS_PHYS = 1; - /* set mips clock to 320MHz */ #if defined(CONFIG_SOC_PNX8335) PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); -- cgit v1.2.3-59-g8ed1b From 87321fddaeb8706a91293dc244408697a0a24ece Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 13:35:03 +0100 Subject: MIPS: Implement __arch_bitrev* using bitswap for MIPSr6 Release 6 of the MIPS architecture introduced the bitswap instruction, which reverses the bits within each byte of a word. Make use of this instruction to implement the __arch_bitrev* functions, which should be faster for most MIPSr6 CPUs, reduces code size slightly and allows us to avoid the lookup table used by the generic implementation, saving 256 bytes in the kernel binary by dropping that. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13204/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/bitrev.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/mips/include/asm/bitrev.h (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2b7af9014cce..95f05826a16f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2000,6 +2000,7 @@ config CPU_MIPSR2 config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 + select HAVE_ARCH_BITREVERSE select MIPS_SPRAM config EVA diff --git a/arch/mips/include/asm/bitrev.h b/arch/mips/include/asm/bitrev.h new file mode 100644 index 000000000000..bc739a404ae3 --- /dev/null +++ b/arch/mips/include/asm/bitrev.h @@ -0,0 +1,30 @@ +#ifndef __MIPS_ASM_BITREV_H__ +#define __MIPS_ASM_BITREV_H__ + +#include + +static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x) +{ + u32 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(__swab32(x))); + return ret; +} + +static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x) +{ + u16 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(__swab16(x))); + return ret; +} + +static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x) +{ + u8 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(x)); + return ret; +} + +#endif /* __MIPS_ASM_BITREV_H__ */ -- cgit v1.2.3-59-g8ed1b From 97b921087fa76b1b0b2a20ae70d0e8b6d394c4ea Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 5 May 2016 09:57:56 +0200 Subject: MIPS: Change my email address The old address is no longer valid. Use the my new one instead. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13201/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h | 2 +- arch/mips/include/asm/mach-lantiq/lantiq.h | 2 +- arch/mips/include/asm/mach-lantiq/lantiq_platform.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/irq.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | 2 +- arch/mips/include/asm/mach-ralink/mt7620.h | 2 +- arch/mips/include/asm/mach-ralink/mt7621.h | 2 +- arch/mips/include/asm/mach-ralink/pinmux.h | 2 +- arch/mips/include/asm/mach-ralink/ralink_regs.h | 2 +- arch/mips/include/asm/mach-ralink/rt288x.h | 2 +- arch/mips/include/asm/mach-ralink/rt305x.h | 2 +- arch/mips/lantiq/Makefile | 2 +- arch/mips/lantiq/clk.c | 2 +- arch/mips/lantiq/clk.h | 2 +- arch/mips/lantiq/early_printk.c | 2 +- arch/mips/lantiq/falcon/prom.c | 2 +- arch/mips/lantiq/falcon/reset.c | 2 +- arch/mips/lantiq/falcon/sysctrl.c | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/lantiq/prom.c | 2 +- arch/mips/lantiq/prom.h | 2 +- arch/mips/lantiq/xway/clk.c | 2 +- arch/mips/lantiq/xway/dcdc.c | 2 +- arch/mips/lantiq/xway/dma.c | 2 +- arch/mips/lantiq/xway/gptu.c | 2 +- arch/mips/lantiq/xway/prom.c | 2 +- arch/mips/lantiq/xway/reset.c | 2 +- arch/mips/lantiq/xway/sysctrl.c | 2 +- arch/mips/lantiq/xway/vmmc.c | 2 +- arch/mips/lantiq/xway/xrx200_phy_fw.c | 4 ++-- arch/mips/pci/fixup-lantiq.c | 2 +- arch/mips/pci/ops-lantiq.c | 2 +- arch/mips/pci/pci-lantiq.c | 2 +- arch/mips/pci/pci-lantiq.h | 2 +- arch/mips/pci/pci-mt7620.c | 2 +- arch/mips/pci/pci-rt2880.c | 2 +- arch/mips/ralink/Makefile | 2 +- arch/mips/ralink/bootrom.c | 2 +- arch/mips/ralink/cevt-rt3352.c | 2 +- arch/mips/ralink/clk.c | 2 +- arch/mips/ralink/common.h | 2 +- arch/mips/ralink/ill_acc.c | 2 +- arch/mips/ralink/irq-gic.c | 2 +- arch/mips/ralink/irq.c | 2 +- arch/mips/ralink/mt7620.c | 2 +- arch/mips/ralink/mt7621.c | 2 +- arch/mips/ralink/of.c | 2 +- arch/mips/ralink/prom.c | 2 +- arch/mips/ralink/reset.c | 2 +- arch/mips/ralink/rt288x.c | 2 +- arch/mips/ralink/rt305x.c | 2 +- arch/mips/ralink/rt3883.c | 2 +- arch/mips/ralink/timer-gic.c | 2 +- arch/mips/ralink/timer.c | 4 ++-- 56 files changed, 58 insertions(+), 58 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h index 98d6a2f14aaf..7023883ca50f 100644 --- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_FALCON_H__ diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h index 4e5ae6523cb4..8064d7a4b33d 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_H__ #define _LANTIQ_H__ diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h index e23bf7c9a2d0..17d2fdcdaef4 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_PLATFORM_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/irq.h b/arch/mips/include/asm/mach-lantiq/xway/irq.h index a1471d2dd0d2..83e5f03cccb5 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/irq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef __LANTIQ_IRQ_H diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h index 5eadfe582529..141076325307 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_XWAY_IRQ_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h index dd6005b75e0c..f87310755319 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_XWAY_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h index 5f8693d5ab12..4901833498f7 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h +++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h @@ -12,7 +12,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #ifndef LTQ_DMA_H__ diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 455d406e8ddf..ece7420f6562 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _MT7620_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/mt7621.h b/arch/mips/include/asm/mach-ralink/mt7621.h index 610b61e3f9df..a672e06fa5fd 100644 --- a/arch/mips/include/asm/mach-ralink/mt7621.h +++ b/arch/mips/include/asm/mach-ralink/mt7621.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #ifndef _MT7621_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/pinmux.h b/arch/mips/include/asm/mach-ralink/pinmux.h index be106cb2e26d..ba8ac331af0c 100644 --- a/arch/mips/include/asm/mach-ralink/pinmux.h +++ b/arch/mips/include/asm/mach-ralink/pinmux.h @@ -3,7 +3,7 @@ * it under the terms of the GNU General Public License version 2 as * publishhed by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #ifndef _RT288X_PINMUX_H__ diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h index 4c9fba68c8b2..9df1a53bcb36 100644 --- a/arch/mips/include/asm/mach-ralink/ralink_regs.h +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h @@ -1,7 +1,7 @@ /* * Ralink SoC register definitions * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h index 03ad716acb42..25ae1042d57b 100644 --- a/arch/mips/include/asm/mach-ralink/rt288x.h +++ b/arch/mips/include/asm/mach-ralink/rt288x.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RT288X_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index 2eea79331a14..ac2d65c04b5f 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RT305X_REGS_H_ diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile index 690257ab86d6..2718652e7466 100644 --- a/arch/mips/lantiq/Makefile +++ b/arch/mips/lantiq/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2010 John Crispin +# Copyright (C) 2010 John Crispin # # 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 diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index a0706fd4ce0a..149f0513c4f5 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2010 Thomas Langer - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include #include diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index 7376ce817eda..e806e048ffc2 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_CLK_H__ diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c index 9b28d0940ef4..44bccaee822b 100644 --- a/arch/mips/lantiq/early_printk.c +++ b/arch/mips/lantiq/early_printk.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c index aa9497947859..75315c0a9fc3 100644 --- a/arch/mips/lantiq/falcon/prom.c +++ b/arch/mips/lantiq/falcon/prom.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2012 Thomas Langer - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c index 568248253426..7a535d72f541 100644 --- a/arch/mips/lantiq/falcon/reset.c +++ b/arch/mips/lantiq/falcon/reset.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2012 Thomas Langer - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index 7edcd4946fc1..2a1b3021589c 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2011 Thomas Langer - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #include diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 2e7f60c9fc5d..ff17669e30a3 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2010 Thomas Langer */ diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index a5c7fec92a97..5f693ac77a0d 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h index bfd2d58c1d69..4b6576c50250 100644 --- a/arch/mips/lantiq/prom.h +++ b/arch/mips/lantiq/prom.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_PROM_H__ diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 07f6d5b0b65e..41fc30d8ef89 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/dcdc.c b/arch/mips/lantiq/xway/dcdc.c index ae8e930f5283..08f7abaadfe5 100644 --- a/arch/mips/lantiq/xway/dcdc.c +++ b/arch/mips/lantiq/xway/dcdc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin * Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH */ diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c index 34a116e840d8..cef811755123 100644 --- a/arch/mips/lantiq/xway/dma.c +++ b/arch/mips/lantiq/xway/dma.c @@ -12,7 +12,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #include diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c index f1492b2db017..0f1bbea1a816 100644 --- a/arch/mips/lantiq/xway/gptu.c +++ b/arch/mips/lantiq/xway/gptu.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin * Copyright (C) 2012 Lantiq GmbH */ diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c index 8f6e02f1e965..9475b2510adb 100644 --- a/arch/mips/lantiq/xway/prom.c +++ b/arch/mips/lantiq/xway/prom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 1f3460877ed5..83fd65d76e81 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 80554e8f6037..236193b5210b 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2011-2012 John Crispin + * Copyright (C) 2011-2012 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/vmmc.c b/arch/mips/lantiq/xway/vmmc.c index d001bc38908a..4625495f9230 100644 --- a/arch/mips/lantiq/xway/vmmc.c +++ b/arch/mips/lantiq/xway/vmmc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c index 199094a40c15..71e518c1e7e7 100644 --- a/arch/mips/lantiq/xway/xrx200_phy_fw.c +++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include @@ -112,6 +112,6 @@ static struct platform_driver xway_phy_driver = { module_platform_driver(xway_phy_driver); -MODULE_AUTHOR("John Crispin "); +MODULE_AUTHOR("John Crispin "); MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader"); MODULE_LICENSE("GPL"); diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c index c2ce41ea61d7..2b5427d3f35c 100644 --- a/arch/mips/pci/fixup-lantiq.c +++ b/arch/mips/pci/fixup-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c index e5738ee26f4f..f51e10899cc2 100644 --- a/arch/mips/pci/ops-lantiq.c +++ b/arch/mips/pci/ops-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 6a15dbd085aa..b9deab17ccf2 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h index 66bf6cd6be3c..0cc71253a497 100644 --- a/arch/mips/pci/pci-lantiq.h +++ b/arch/mips/pci/pci-lantiq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_PCI_H__ diff --git a/arch/mips/pci/pci-mt7620.c b/arch/mips/pci/pci-mt7620.c index 1ae932c2d78b..6ce816201699 100644 --- a/arch/mips/pci/pci-mt7620.c +++ b/arch/mips/pci/pci-mt7620.c @@ -2,7 +2,7 @@ * Ralink MT7620A SoC PCI support * * Copyright (C) 2007-2013 Bruce Chang (Mediatek) - * Copyright (C) 2013-2016 John Crispin + * Copyright (C) 2013-2016 John Crispin * * 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 diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c index a245cad4372a..f2a1050168d9 100644 --- a/arch/mips/pci/pci-rt2880.c +++ b/arch/mips/pci/pci-rt2880.c @@ -1,7 +1,7 @@ /* * Ralink RT288x SoC PCI register definitions * - * Copyright (C) 2009 John Crispin + * Copyright (C) 2009 John Crispin * Copyright (C) 2009 Gabor Juhos * * Parts of this file are based on Ralink's 2.6.21 BSP diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 0d1795a0321e..fe3471533820 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -4,7 +4,7 @@ # Makefile for the Ralink common stuff # # Copyright (C) 2009-2011 Gabor Juhos -# Copyright (C) 2013 John Crispin +# Copyright (C) 2013 John Crispin obj-y := prom.o of.o reset.o diff --git a/arch/mips/ralink/bootrom.c b/arch/mips/ralink/bootrom.c index 5403468394fb..e1fa5972a81d 100644 --- a/arch/mips/ralink/bootrom.c +++ b/arch/mips/ralink/bootrom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index e46f91f971c5..3ad0b0794f7d 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2013 by John Crispin + * Copyright (C) 2013 by John Crispin */ #include diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index 25c4a61779f1..ebaa7cc0e995 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2011 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 8e7d8e618fb9..b8245d0940d6 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RALINK_COMMON_H__ diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c index e10d10b9e82a..765d5ba98fa2 100644 --- a/arch/mips/ralink/ill_acc.c +++ b/arch/mips/ralink/ill_acc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/irq-gic.c b/arch/mips/ralink/irq-gic.c index 50d6c55ab1de..2058280450b5 100644 --- a/arch/mips/ralink/irq-gic.c +++ b/arch/mips/ralink/irq-gic.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 4cf77f358395..4911c1445f1a 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2009 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 0d3d1a97895f..2c623f6bca08 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c index e9b9fa3e1e51..a45bbbe97ac5 100644 --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index f9eda5d8f82c..0aa67a2d0ae6 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Imre Kaloz * Copyright (C) 2008-2009 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c index 39a9142f71be..5a73c5e14221 100644 --- a/arch/mips/ralink/prom.c +++ b/arch/mips/ralink/prom.c @@ -5,7 +5,7 @@ * * Copyright (C) 2009 Gabor Juhos * Copyright (C) 2010 Joonas Lahtinen - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index 09ccdd1b8f4d..64543d66e76b 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008-2009 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index 3c84166ebcb7..285796e6d75c 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index d7c4ba43a428..c8a28c4bf29e 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index fafec947b27d..4cef9162bd9b 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008 Imre Kaloz * Copyright (C) 2008-2011 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/timer-gic.c b/arch/mips/ralink/timer-gic.c index 5b4f186bcf95..069771dbec42 100644 --- a/arch/mips/ralink/timer-gic.c +++ b/arch/mips/ralink/timer-gic.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c index 82c72a15bf75..b0343ff336c5 100644 --- a/arch/mips/ralink/timer.c +++ b/arch/mips/ralink/timer.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include @@ -180,5 +180,5 @@ static struct platform_driver rt_timer_driver = { module_platform_driver(rt_timer_driver); MODULE_DESCRIPTION("Ralink RT2880 timer"); -MODULE_AUTHOR("John Crispin Date: Fri, 6 May 2016 14:36:18 +0100 Subject: MIPS: KVM/locore.S: Don't preserve host ASID around vcpu_run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIPS KVM uses different ASIDs for guest execution than for the host. The host ASID is saved on the stack when entering the guest with __kvm_mips_vcpu_run(), and restored again before returning back to the caller (exit to userland). - This does not take into account that pre-emption may have taken place during that time, which may have started a new ASID cycle and resulted in that process' ASID being invalidated and reused. - This does not take into account that the process may have migrated to a different CPU during that time, with a different ASID assignment since they are managed per-CPU. - It is actually redundant, since the host ASID will be restored correctly by kvm_arch_vcpu_put(), which is called almost immediately after kvm_arch_vcpu_ioctl_run() returns. Therefore drop this code from locore.S Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13206/ Signed-off-by: Ralf Baechle --- arch/mips/kvm/locore.S | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch') diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 81687ab1b523..c24facc85357 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -32,7 +32,6 @@ EXPORT(x); /* Overload, Danger Will Robinson!! */ -#define PT_HOST_ASID PT_BVADDR #define PT_HOST_USERLOCAL PT_EPC #define CP0_DDATA_LO $28,3 @@ -104,11 +103,6 @@ FEXPORT(__kvm_mips_vcpu_run) mfc0 v0, CP0_STATUS LONG_S v0, PT_STATUS(k1) - /* Save host ASID, shove it into the BVADDR location */ - mfc0 v1, CP0_ENTRYHI - andi v1, 0xff - LONG_S v1, PT_HOST_ASID(k1) - /* Save DDATA_LO, will be used to store pointer to vcpu */ mfc0 v1, CP0_DDATA_LO LONG_S v1, PT_HOST_USERLOCAL(k1) @@ -551,12 +545,6 @@ __kvm_mips_return_to_host: LONG_L k0, PT_HOST_USERLOCAL(k1) mtc0 k0, CP0_DDATA_LO - /* Restore host ASID */ - LONG_L k0, PT_HOST_ASID(sp) - andi k0, 0xff - mtc0 k0,CP0_ENTRYHI - ehb - /* Load context saved on the host stack */ LONG_L $0, PT_R0(k1) LONG_L $1, PT_R1(k1) -- cgit v1.2.3-59-g8ed1b From 9b5c3399584b6f6aa755dbe11e3cef5776fd279d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 6 May 2016 14:36:19 +0100 Subject: MIPS: Add & use CP0_EntryHi ASID definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add definitions for the ASID field in CP0_EntryHi (along with the soon to be used ASIDX field), and use them in a few previously hardcoded cases. Signed-off-by: James Hogan Cc: Manuel Lauss Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13205/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 2 ++ arch/mips/kernel/genex.S | 2 +- arch/mips/kvm/locore.S | 4 ++-- arch/mips/pci/pci-alchemy.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 1e9d337fb077..b7705ef09df2 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -229,6 +229,8 @@ /* MIPS32/64 EntryHI bit definitions */ #define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10) +#define MIPS_ENTRYHI_ASIDX (_ULCAST_(0x3) << 8) +#define MIPS_ENTRYHI_ASID (_ULCAST_(0xff) << 0) /* * R4x00 interrupt enable / cause bits diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index baa7b6fc0a60..17374aef6f00 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .set noreorder /* check if TLB contains a entry for EPC */ MFC0 k1, CP0_ENTRYHI - andi k1, 0xff /* ASID_MASK */ + andi k1, MIPS_ENTRYHI_ASID MFC0 k0, CP0_EPC PTR_SRL k0, _PAGE_SHIFT + 1 PTR_SLL k0, _PAGE_SHIFT + 1 diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index c24facc85357..308706493fd5 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -164,7 +164,7 @@ FEXPORT(__kvm_mips_load_asid) INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) - andi k0, k0, 0xff + andi k0, k0, MIPS_ENTRYHI_ASID mtc0 k0, CP0_ENTRYHI ehb @@ -483,7 +483,7 @@ __kvm_mips_return_to_guest: INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) - andi k0, k0, 0xff + andi k0, k0, MIPS_ENTRYHI_ASID mtc0 k0, CP0_ENTRYHI ehb diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index 28952637a862..c8994c156e2d 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -76,7 +76,7 @@ static void mod_wired_entry(int entry, unsigned long entrylo0, unsigned long old_ctx; /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & 0xff; + old_ctx = read_c0_entryhi() & MIPS_ENTRYHI_ASID; old_pagemask = read_c0_pagemask(); write_c0_index(entry); write_c0_pagemask(pagemask); -- cgit v1.2.3-59-g8ed1b From ca64c2beecd43e9621f5265edf14a76f7a2ffd7b Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:20 +0100 Subject: MIPS: KVM: Abstract guest ASID mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for supporting varied widths of ASID mask in the kernel in general, switch KVM's guest ASIDs to a new KVM_ENTRYHI_ASID definition based on the 8-bit MIPS_ENTRYHI_ASID instead of ASID_MASK. It could potentially be used to support extended guest ASIDs in the future. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13207/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/kvm_host.h | 5 +++-- arch/mips/kvm/emulate.c | 25 +++++++++++++------------ arch/mips/kvm/tlb.c | 3 ++- 3 files changed, 18 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index f6b12790716c..b76e132c87e4 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -311,17 +311,18 @@ enum emulation_result { #define MIPS3_PG_FRAME 0x3fffffc0 #define VPN2_MASK 0xffffe000 +#define KVM_ENTRYHI_ASID MIPS_ENTRYHI_ASID #define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \ ((x).tlb_lo1 & MIPS3_PG_G)) #define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK) -#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK) +#define TLB_ASID(x) ((x).tlb_hi & KVM_ENTRYHI_ASID) #define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \ ? ((x).tlb_lo1 & MIPS3_PG_V) \ : ((x).tlb_lo0 & MIPS3_PG_V)) #define TLB_HI_VPN2_HIT(x, y) ((TLB_VPN2(x) & ~(x).tlb_mask) == \ ((y) & VPN2_MASK & ~(x).tlb_mask)) #define TLB_HI_ASID_HIT(x, y) (TLB_IS_GLOBAL(x) || \ - TLB_ASID(x) == ((y) & ASID_MASK)) + TLB_ASID(x) == ((y) & KVM_ENTRYHI_ASID)) struct kvm_mips_tlb { long tlb_mask; diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index b37954cc880d..8e945e866a73 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1068,15 +1068,15 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, kvm_read_c0_guest_ebase(cop0)); } else if (rd == MIPS_CP0_TLB_HI && sel == 0) { uint32_t nasid = - vcpu->arch.gprs[rt] & ASID_MASK; + vcpu->arch.gprs[rt] & KVM_ENTRYHI_ASID; if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) && ((kvm_read_c0_guest_entryhi(cop0) & - ASID_MASK) != nasid)) { + KVM_ENTRYHI_ASID) != nasid)) { kvm_debug("MTCz, change ASID from %#lx to %#lx\n", kvm_read_c0_guest_entryhi(cop0) - & ASID_MASK, + & KVM_ENTRYHI_ASID, vcpu->arch.gprs[rt] - & ASID_MASK); + & KVM_ENTRYHI_ASID); /* Blow away the shadow host TLBs */ kvm_mips_flush_host_tlb(1); @@ -1620,7 +1620,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, */ index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) | (kvm_read_c0_guest_entryhi - (cop0) & ASID_MASK)); + (cop0) & KVM_ENTRYHI_ASID)); if (index < 0) { vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK); @@ -1786,7 +1786,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1833,7 +1833,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause, struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1878,7 +1878,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1922,7 +1922,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1967,7 +1967,7 @@ enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc, #ifdef DEBUG struct mips_coproc *cop0 = vcpu->arch.cop0; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); int index; /* If address not in the guest TLB, then we are in trouble */ @@ -1994,7 +1994,7 @@ enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause, { struct mips_coproc *cop0 = vcpu->arch.cop0; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); struct kvm_vcpu_arch *arch = &vcpu->arch; if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { @@ -2569,7 +2569,8 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause, */ index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK)); + (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & + KVM_ENTRYHI_ASID)); if (index < 0) { if (exccode == EXCCODE_TLBL) { er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu); diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index e0e1d0a611fc..52d87280f865 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -748,7 +748,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu) inst = *(opc); } else { vpn2 = (unsigned long) opc & VPN2_MASK; - asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK; + asid = kvm_read_c0_guest_entryhi(cop0) & + KVM_ENTRYHI_ASID; index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid); if (index < 0) { kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n", -- cgit v1.2.3-59-g8ed1b From 1300fcd5e1754b654954717410c7035c0daac605 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 6 May 2016 14:36:21 +0100 Subject: MIPS: KVM/locore.S: Only preserve callee saved registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update __kvm_mips_vcpu_run() to only save and restore callee saved registers. It is always called using the standard ABIs, so the caller will preserve any other registers that need preserving. Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13208/ Signed-off-by: Ralf Baechle --- arch/mips/kvm/locore.S | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 308706493fd5..3ea522e4954b 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -53,40 +53,14 @@ FEXPORT(__kvm_mips_vcpu_run) /* k0/k1 not being used in host kernel context */ INT_ADDIU k1, sp, -PT_SIZE - LONG_S $0, PT_R0(k1) - LONG_S $1, PT_R1(k1) - LONG_S $2, PT_R2(k1) - LONG_S $3, PT_R3(k1) - - LONG_S $4, PT_R4(k1) - LONG_S $5, PT_R5(k1) - LONG_S $6, PT_R6(k1) - LONG_S $7, PT_R7(k1) - - LONG_S $8, PT_R8(k1) - LONG_S $9, PT_R9(k1) - LONG_S $10, PT_R10(k1) - LONG_S $11, PT_R11(k1) - LONG_S $12, PT_R12(k1) - LONG_S $13, PT_R13(k1) - LONG_S $14, PT_R14(k1) - LONG_S $15, PT_R15(k1) LONG_S $16, PT_R16(k1) LONG_S $17, PT_R17(k1) - LONG_S $18, PT_R18(k1) LONG_S $19, PT_R19(k1) LONG_S $20, PT_R20(k1) LONG_S $21, PT_R21(k1) LONG_S $22, PT_R22(k1) LONG_S $23, PT_R23(k1) - LONG_S $24, PT_R24(k1) - LONG_S $25, PT_R25(k1) - - /* - * XXXKYMA k0/k1 not saved, not being used if we got here through - * an ioctl() - */ LONG_S $28, PT_R28(k1) LONG_S $29, PT_R29(k1) @@ -545,10 +519,6 @@ __kvm_mips_return_to_host: LONG_L k0, PT_HOST_USERLOCAL(k1) mtc0 k0, CP0_DDATA_LO - /* Load context saved on the host stack */ - LONG_L $0, PT_R0(k1) - LONG_L $1, PT_R1(k1) - /* * r2/v0 is the return code, shift it down by 2 (arithmetic) * to recover the err code @@ -556,19 +526,7 @@ __kvm_mips_return_to_host: INT_SRA k0, v0, 2 move $2, k0 - LONG_L $3, PT_R3(k1) - LONG_L $4, PT_R4(k1) - LONG_L $5, PT_R5(k1) - LONG_L $6, PT_R6(k1) - LONG_L $7, PT_R7(k1) - LONG_L $8, PT_R8(k1) - LONG_L $9, PT_R9(k1) - LONG_L $10, PT_R10(k1) - LONG_L $11, PT_R11(k1) - LONG_L $12, PT_R12(k1) - LONG_L $13, PT_R13(k1) - LONG_L $14, PT_R14(k1) - LONG_L $15, PT_R15(k1) + /* Load context saved on the host stack */ LONG_L $16, PT_R16(k1) LONG_L $17, PT_R17(k1) LONG_L $18, PT_R18(k1) @@ -577,10 +535,6 @@ __kvm_mips_return_to_host: LONG_L $21, PT_R21(k1) LONG_L $22, PT_R22(k1) LONG_L $23, PT_R23(k1) - LONG_L $24, PT_R24(k1) - LONG_L $25, PT_R25(k1) - - /* Host k0/k1 were not saved */ LONG_L $28, PT_R28(k1) LONG_L $29, PT_R29(k1) -- cgit v1.2.3-59-g8ed1b From f1b711c638c7df56112eff8e9661c91202782516 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 6 May 2016 14:36:22 +0100 Subject: MIPS: KVM/locore.S: Relax noat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the at register ($1) is no longer saved by __kvm_mips_vcpu_run(), relax the noat assembler directive so that it only applies around code where at is restored before entering guest, and saved after exiting guest. Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13209/ Signed-off-by: Ralf Baechle --- arch/mips/kvm/locore.S | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 3ea522e4954b..1f2167bc847d 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -48,7 +48,6 @@ * a1: vcpu */ .set noreorder - .set noat FEXPORT(__kvm_mips_vcpu_run) /* k0/k1 not being used in host kernel context */ @@ -145,6 +144,7 @@ FEXPORT(__kvm_mips_load_asid) /* Disable RDHWR access */ mtc0 zero, CP0_HWRENA + .set noat /* Now load up the Guest Context from VCPU */ LONG_L $1, VCPU_R1(k1) LONG_L $2, VCPU_R2(k1) @@ -256,6 +256,8 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) LONG_S $30, VCPU_R30(k1) LONG_S $31, VCPU_R31(k1) + .set at + /* We need to save hi/lo and restore them on the way out */ mfhi t0 LONG_S t0, VCPU_HI(k1) @@ -307,9 +309,7 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) /* load up the host EBASE */ mfc0 v0, CP0_STATUS - .set at or k0, v0, ST0_BEV - .set noat mtc0 k0, CP0_STATUS ehb @@ -321,7 +321,6 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't * trigger FPE for pending exceptions. */ - .set at and v1, v0, ST0_CU1 beqz v1, 1f nop @@ -331,7 +330,6 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) sw t0, VCPU_FCR31(k1) ctc1 zero,fcr31 .set pop - .set noat 1: #ifdef CONFIG_CPU_HAS_MSA @@ -354,10 +352,8 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) #endif /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */ - .set at and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE) or v0, v0, ST0_CU0 - .set noat mtc0 v0, CP0_STATUS ehb @@ -424,18 +420,14 @@ __kvm_mips_return_to_guest: /* Switch EBASE back to the one used by KVM */ mfc0 v1, CP0_STATUS - .set at or k0, v1, ST0_BEV - .set noat mtc0 k0, CP0_STATUS ehb mtc0 t0, CP0_EBASE /* Setup status register for running guest in UM */ - .set at or v1, v1, (ST0_EXL | KSU_USER | ST0_IE) and v1, v1, ~(ST0_CU0 | ST0_MX) - .set noat mtc0 v1, CP0_STATUS ehb @@ -464,6 +456,7 @@ __kvm_mips_return_to_guest: /* Disable RDHWR access */ mtc0 zero, CP0_HWRENA + .set noat /* load the guest context from VCPU and return */ LONG_L $0, VCPU_R0(k1) LONG_L $1, VCPU_R1(k1) @@ -509,6 +502,7 @@ FEXPORT(__kvm_mips_skip_guest_restore) LONG_L k1, VCPU_R27(k1) eret + .set at __kvm_mips_return_to_host: /* EBASE is already pointing to Linux */ -- cgit v1.2.3-59-g8ed1b From 4edf00a46bee692f62578b5280c5774f9b65a08f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:23 +0100 Subject: MIPS: Retrieve ASID masks using function accepting struct cpuinfo_mips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for supporting variable ASID masks, retrieve ASID masks using functions in asm/cpu-info.h which accept struct cpuinfo_mips. This will allow those functions to determine the ASID mask based upon the CPU in a later patch. This also allows for the r3k & r8k cases to be handled in Kconfig, which is arguably cleaner than the previous #ifdefs. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13210/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 11 ++++++++++ arch/mips/include/asm/cpu-info.h | 10 +++++++++ arch/mips/include/asm/mmu_context.h | 41 ++++++++++++++++--------------------- arch/mips/kernel/traps.c | 2 +- arch/mips/kvm/tlb.c | 30 +++++++++++++++++---------- arch/mips/lib/dump_tlb.c | 10 +++++---- arch/mips/lib/r3k_dump_tlb.c | 9 ++++---- arch/mips/mm/tlb-r3k.c | 24 +++++++++++++--------- arch/mips/mm/tlb-r4k.c | 2 +- arch/mips/mm/tlb-r8k.c | 2 +- 10 files changed, 86 insertions(+), 55 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 95f05826a16f..0cab0da2ab55 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2449,6 +2449,17 @@ config CPU_R4000_WORKAROUNDS config CPU_R4400_WORKAROUNDS bool +config MIPS_ASID_SHIFT + int + default 6 if CPU_R3000 || CPU_TX39XX + default 4 if CPU_R8000 + default 0 + +config MIPS_ASID_BITS + int + default 6 if CPU_R3000 || CPU_TX39XX + default 8 + # # - Highmem only makes sense for the 32-bit kernel. # - The current highmem code will only work properly on physically indexed diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index b090aa51d644..1ae26a393153 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -132,4 +132,14 @@ struct proc_cpuinfo_notifier_args { # define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; }) #endif +static inline unsigned long cpu_asid_inc(void) +{ + return 1 << CONFIG_MIPS_ASID_SHIFT; +} + +static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo) +{ + return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT; +} + #endif /* __ASM_CPU_INFO_H */ diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index 45914b59824c..fc57e135cb0a 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -65,37 +65,32 @@ extern unsigned long pgd_current[]; back_to_back_c0_hazard(); \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/ -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) -#define ASID_INC 0x40 -#define ASID_MASK 0xfc0 - -#elif defined(CONFIG_CPU_R8000) - -#define ASID_INC 0x10 -#define ASID_MASK 0xff0 - -#else /* FIXME: not correct for R6000 */ +/* + * All unused by hardware upper bits will be considered + * as a software asid extension. + */ +static unsigned long asid_version_mask(unsigned int cpu) +{ + unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]); -#define ASID_INC 0x1 -#define ASID_MASK 0xff + return ~(asid_mask | (asid_mask - 1)); +} -#endif +static unsigned long asid_first_version(unsigned int cpu) +{ + return ~asid_version_mask(cpu) + 1; +} #define cpu_context(cpu, mm) ((mm)->context.asid[cpu]) -#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) #define asid_cache(cpu) (cpu_data[cpu].asid_cache) +#define cpu_asid(cpu, mm) \ + (cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu])) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } -/* - * All unused by hardware upper bits will be considered - * as a software asid extension. - */ -#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1))) -#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1) /* Normal, classic MIPS get_new_mmu_context */ static inline void @@ -104,7 +99,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) extern void kvm_local_flush_tlb_all(void); unsigned long asid = asid_cache(cpu); - if (! ((asid += ASID_INC) & ASID_MASK) ) { + if (!((asid += cpu_asid_inc()) & cpu_asid_mask(&cpu_data[cpu]))) { if (cpu_has_vtag_icache) flush_icache_all(); #ifdef CONFIG_KVM @@ -113,7 +108,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) local_flush_tlb_all(); /* start new asid cycle */ #endif if (!asid) /* fix version if needed */ - asid = ASID_FIRST_VERSION; + asid = asid_first_version(cpu); } cpu_context(cpu, mm) = asid_cache(cpu) = asid; @@ -145,7 +140,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, htw_stop(); /* Check if our ASID is of an older version and thus invalid */ - if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) + if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & asid_version_mask(cpu)) get_new_mmu_context(next, cpu); write_c0_entryhi(cpu_asid(cpu, next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index f586b8b23f60..56f4161b98b9 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2136,7 +2136,7 @@ void per_cpu_trap_init(bool is_boot_cpu) } if (!cpu_data[cpu].asid_cache) - cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; + cpu_data[cpu].asid_cache = asid_first_version(cpu); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index 52d87280f865..b9c52c1d35d6 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -49,12 +49,18 @@ EXPORT_SYMBOL_GPL(kvm_mips_is_error_pfn); uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu) { - return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK; + int cpu = smp_processor_id(); + + return vcpu->arch.guest_kernel_asid[cpu] & + cpu_asid_mask(&cpu_data[cpu]); } uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu) { - return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK; + int cpu = smp_processor_id(); + + return vcpu->arch.guest_user_asid[cpu] & + cpu_asid_mask(&cpu_data[cpu]); } inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu) @@ -78,7 +84,8 @@ void kvm_mips_dump_host_tlbs(void) old_pagemask = read_c0_pagemask(); kvm_info("HOST TLBs:\n"); - kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK); + kvm_info("ASID: %#lx\n", read_c0_entryhi() & + cpu_asid_mask(¤t_cpu_data)); for (i = 0; i < current_cpu_data.tlbsize; i++) { write_c0_index(i); @@ -564,15 +571,15 @@ void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, { unsigned long asid = asid_cache(cpu); - asid += ASID_INC; - if (!(asid & ASID_MASK)) { + asid += cpu_asid_inc(); + if (!(asid & cpu_asid_mask(&cpu_data[cpu]))) { if (cpu_has_vtag_icache) flush_icache_all(); kvm_local_flush_tlb_all(); /* start new asid cycle */ if (!asid) /* fix version if needed */ - asid = ASID_FIRST_VERSION; + asid = asid_first_version(cpu); } cpu_context(cpu, mm) = asid_cache(cpu) = asid; @@ -627,6 +634,7 @@ static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu) /* Restore ASID once we are scheduled back after preemption */ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { + unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]); unsigned long flags; int newasid = 0; @@ -637,7 +645,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) local_irq_save(flags); if ((vcpu->arch.guest_kernel_asid[cpu] ^ asid_cache(cpu)) & - ASID_VERSION_MASK) { + asid_version_mask(cpu)) { kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu); vcpu->arch.guest_kernel_asid[cpu] = vcpu->arch.guest_kernel_mm.context.asid[cpu]; @@ -672,7 +680,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) */ if (current->flags & PF_VCPU) { write_c0_entryhi(vcpu->arch. - preempt_entryhi & ASID_MASK); + preempt_entryhi & asid_mask); ehb(); } } else { @@ -687,11 +695,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (KVM_GUEST_KERNEL_MODE(vcpu)) write_c0_entryhi(vcpu->arch. guest_kernel_asid[cpu] & - ASID_MASK); + asid_mask); else write_c0_entryhi(vcpu->arch. guest_user_asid[cpu] & - ASID_MASK); + asid_mask); ehb(); } } @@ -721,7 +729,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) kvm_mips_callbacks->vcpu_get_regs(vcpu); if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) & - ASID_VERSION_MASK)) { + asid_version_mask(cpu))) { kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__, cpu_context(cpu, current->mm)); drop_mmu_context(current->mm, cpu); diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 92a37319efbe..3283aa7423e4 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -73,6 +73,8 @@ static void dump_tlb(int first, int last) unsigned long s_entryhi, entryhi, asid; unsigned long long entrylo0, entrylo1, pa; unsigned int s_index, s_pagemask, pagemask, c0, c1, i; + unsigned long asidmask = cpu_asid_mask(¤t_cpu_data); + int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4); #ifdef CONFIG_32BIT bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA); int pwidth = xpa ? 11 : 8; @@ -86,7 +88,7 @@ static void dump_tlb(int first, int last) s_pagemask = read_c0_pagemask(); s_entryhi = read_c0_entryhi(); s_index = read_c0_index(); - asid = s_entryhi & 0xff; + asid = s_entryhi & asidmask; for (i = first; i <= last; i++) { write_c0_index(i); @@ -115,7 +117,7 @@ static void dump_tlb(int first, int last) * due to duplicate TLB entry. */ if (!((entrylo0 | entrylo1) & ENTRYLO_G) && - (entryhi & 0xff) != asid) + (entryhi & asidmask) != asid) continue; /* @@ -126,9 +128,9 @@ static void dump_tlb(int first, int last) c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; - printk("va=%0*lx asid=%02lx\n", + printk("va=%0*lx asid=%0*lx\n", vwidth, (entryhi & ~0x1fffUL), - entryhi & 0xff); + asidwidth, entryhi & asidmask); /* RI/XI are in awkward places, so mask them off separately */ pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); if (xpa) diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index cfcbb5218b59..744f4a7bc49d 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c @@ -29,9 +29,10 @@ static void dump_tlb(int first, int last) { int i; unsigned int asid; - unsigned long entryhi, entrylo0; + unsigned long entryhi, entrylo0, asid_mask; - asid = read_c0_entryhi() & ASID_MASK; + asid_mask = cpu_asid_mask(¤t_cpu_data); + asid = read_c0_entryhi() & asid_mask; for (i = first; i <= last; i++) { write_c0_index(i<<8); @@ -46,7 +47,7 @@ static void dump_tlb(int first, int last) /* Unused entries have a virtual address of KSEG0. */ if ((entryhi & PAGE_MASK) != KSEG0 && (entrylo0 & R3K_ENTRYLO_G || - (entryhi & ASID_MASK) == asid)) { + (entryhi & asid_mask) == asid)) { /* * Only print entries in use */ @@ -55,7 +56,7 @@ static void dump_tlb(int first, int last) printk("va=%08lx asid=%08lx" " [pa=%06lx n=%d d=%d v=%d g=%d]", entryhi & PAGE_MASK, - entryhi & ASID_MASK, + entryhi & asid_mask, entrylo0 & PAGE_MASK, (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index b4f366f7c0f5..1290b995695d 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -43,7 +43,7 @@ static void local_flush_tlb_from(int entry) { unsigned long old_ctx; - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); write_c0_entrylo0(0); while (entry < current_cpu_data.tlbsize) { write_c0_index(entry << 8); @@ -81,6 +81,7 @@ void local_flush_tlb_mm(struct mm_struct *mm) void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); @@ -89,13 +90,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, #ifdef DEBUG_TLB printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", - cpu_context(cpu, mm) & ASID_MASK, start, end); + cpu_context(cpu, mm) & asid_mask, start, end); #endif local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; if (size <= current_cpu_data.tlbsize) { - int oldpid = read_c0_entryhi() & ASID_MASK; - int newpid = cpu_context(cpu, mm) & ASID_MASK; + int oldpid = read_c0_entryhi() & asid_mask; + int newpid = cpu_context(cpu, mm) & asid_mask; start &= PAGE_MASK; end += PAGE_SIZE - 1; @@ -159,6 +160,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); int cpu = smp_processor_id(); if (cpu_context(cpu, vma->vm_mm) != 0) { @@ -168,10 +170,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) #ifdef DEBUG_TLB printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page); #endif - newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK; + newpid = cpu_context(cpu, vma->vm_mm) & asid_mask; page &= PAGE_MASK; local_irq_save(flags); - oldpid = read_c0_entryhi() & ASID_MASK; + oldpid = read_c0_entryhi() & asid_mask; write_c0_entryhi(page | newpid); BARRIER; tlb_probe(); @@ -190,6 +192,7 @@ finish: void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); unsigned long flags; int idx, pid; @@ -199,10 +202,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) if (current->active_mm != vma->vm_mm) return; - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & asid_mask; #ifdef DEBUG_TLB - if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) { + if ((pid != (cpu_context(cpu, vma->vm_mm) & asid_mask)) || (cpu_context(cpu, vma->vm_mm) == 0)) { printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n", (cpu_context(cpu, vma->vm_mm)), pid); } @@ -228,6 +231,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); unsigned long flags; unsigned long old_ctx; static unsigned long wired = 0; @@ -243,7 +247,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, local_irq_save(flags); /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & asid_mask; old_pagemask = read_c0_pagemask(); w = read_c0_wired(); write_c0_wired(w + 1); @@ -266,7 +270,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, #endif local_irq_save(flags); - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & asid_mask; write_c0_entrylo0(entrylo0); write_c0_entryhi(entryhi); write_c0_index(wired); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 4c3362b46066..61f1f1ba4a17 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -304,7 +304,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) local_irq_save(flags); htw_stop(); - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); address &= (PAGE_MASK << 1); write_c0_entryhi(address | pid); pgdp = pgd_offset(vma->vm_mm, address); diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 138a2ec7cc6b..e86e2e55ad3e 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -194,7 +194,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) if (current->active_mm != vma->vm_mm) return; - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); local_irq_save(flags); address &= PAGE_MASK; -- cgit v1.2.3-59-g8ed1b From 2db003a5ddee986d4bc67c069ee3aa1b1b320f1d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:24 +0100 Subject: MIPS: Support extended ASIDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for extended ASIDs as determined by the Config4.AE bit. Since the only supported CPUs known to implement this are Netlogic XLP and MIPS I6400, select this variable ASID support based upon CONFIG_CPU_XLP and CONFIG_CPU_MIPSR6. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Jayachandran C. Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13211/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 6 ++++++ arch/mips/include/asm/cpu-info.h | 14 ++++++++++++++ arch/mips/kernel/asm-offsets.c | 10 ++++++++++ arch/mips/kernel/cpu-probe.c | 13 +++++++++++++ arch/mips/kernel/genex.S | 2 +- arch/mips/kvm/locore.S | 14 ++++++++++++++ 6 files changed, 58 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0cab0da2ab55..5cc5b621ae69 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1706,6 +1706,7 @@ config CPU_XLP select CPU_HAS_PREFETCH select CPU_MIPSR2 select CPU_SUPPORTS_HUGEPAGES + select MIPS_ASID_BITS_VARIABLE help Netlogic Microsystems XLP processors. endchoice @@ -2001,6 +2002,7 @@ config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 select HAVE_ARCH_BITREVERSE + select MIPS_ASID_BITS_VARIABLE select MIPS_SPRAM config EVA @@ -2457,9 +2459,13 @@ config MIPS_ASID_SHIFT config MIPS_ASID_BITS int + default 0 if MIPS_ASID_BITS_VARIABLE default 6 if CPU_R3000 || CPU_TX39XX default 8 +config MIPS_ASID_BITS_VARIABLE + bool + # # - Highmem only makes sense for the 32-bit kernel. # - The current highmem code will only work properly on physically indexed diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 1ae26a393153..392da7e6fc72 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -40,6 +40,9 @@ struct cache_desc { struct cpuinfo_mips { unsigned long asid_cache; +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + unsigned long asid_mask; +#endif /* * Capability and feature descriptor structure for MIPS CPU @@ -139,7 +142,18 @@ static inline unsigned long cpu_asid_inc(void) static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo) { +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + return cpuinfo->asid_mask; +#endif return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT; } +static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo, + unsigned long asid_mask) +{ +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + cpuinfo->asid_mask = asid_mask; +#endif +} + #endif /* __ASM_CPU_INFO_H */ diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 154e2039ea5e..1ea973b2abb1 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -338,6 +339,15 @@ void output_pm_defines(void) } #endif +void output_cpuinfo_defines(void) +{ + COMMENT(" MIPS cpuinfo offsets. "); + DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips)); +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask); +#endif +} + void output_kvm_defines(void) { COMMENT(" KVM/MIPS Specfic offsets. "); diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 064ab389e964..5ca4fefb1344 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -732,6 +732,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) unsigned int newcf4; unsigned int mmuextdef; unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE; + unsigned long asid_mask; config4 = read_c0_config4(); @@ -792,6 +793,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) c->kscratch_mask = (config4 >> 16) & 0xff; + asid_mask = MIPS_ENTRYHI_ASID; + if (config4 & MIPS_CONF4_AE) + asid_mask |= MIPS_ENTRYHI_ASIDX; + set_cpu_asid_mask(c, asid_mask); + + /* + * Warn if the computed ASID mask doesn't match the mask the kernel + * is built for. This may indicate either a serious problem or an + * easy optimisation opportunity, but either way should be addressed. + */ + WARN_ON(asid_mask != cpu_asid_mask(c)); + return config4 & MIPS_CONF_M; } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 17374aef6f00..bff9644b9ad1 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .set noreorder /* check if TLB contains a entry for EPC */ MFC0 k1, CP0_ENTRYHI - andi k1, MIPS_ENTRYHI_ASID + andi k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX MFC0 k0, CP0_EPC PTR_SRL k0, _PAGE_SHIFT + 1 PTR_SLL k0, _PAGE_SHIFT + 1 diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 1f2167bc847d..3ef03009de5f 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -137,7 +137,14 @@ FEXPORT(__kvm_mips_load_asid) INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + li t3, CPUINFO_SIZE/4 + mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */ + LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2) + and k0, k0, t2 +#else andi k0, k0, MIPS_ENTRYHI_ASID +#endif mtc0 k0, CP0_ENTRYHI ehb @@ -449,7 +456,14 @@ __kvm_mips_return_to_guest: INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + li t3, CPUINFO_SIZE/4 + mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */ + LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2) + and k0, k0, t2 +#else andi k0, k0, MIPS_ENTRYHI_ASID +#endif mtc0 k0, CP0_ENTRYHI ehb -- cgit v1.2.3-59-g8ed1b From 105c22c5cf3f420ce5ab792b3577ef330f1f6133 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 29 Apr 2016 17:29:29 +0100 Subject: MIPS: genex: Indent delay slots & clean whitespace Various branches and jumps in noreorder parts of genex.S don't have their delay slot instructions indented conventionally with the extra space. Fix these, as well as various other inconsistent whitespace problems in this file, such as spaces used after some opcodes instead of a tab. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13196/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/genex.S | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index bff9644b9ad1..17326a90d53c 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -130,7 +130,7 @@ LEAF(__r4k_wait) /* end of rollback region (the region size must be power of two) */ 1: jr ra - nop + nop .set pop END(__r4k_wait) @@ -172,7 +172,7 @@ NESTED(handle_int, PT_SIZE, sp) mfc0 k0, CP0_EPC .set noreorder j k0 - rfe + rfe #else and k0, ST0_IE bnez k0, 1f @@ -189,7 +189,7 @@ NESTED(handle_int, PT_SIZE, sp) LONG_L s0, TI_REGS($28) LONG_S sp, TI_REGS($28) PTR_LA ra, ret_from_irq - PTR_LA v0, plat_irq_dispatch + PTR_LA v0, plat_irq_dispatch jr v0 #ifdef CONFIG_CPU_MICROMIPS nop @@ -292,7 +292,7 @@ ejtag_return: MFC0 k0, CP0_DESAVE .set mips32 deret - .set pop + .set pop END(ejtag_debug_handler) /* @@ -329,10 +329,10 @@ NESTED(nmi_handler, PT_SIZE, sp) * Clear BEV - required for page fault exception handler to work */ mfc0 k0, CP0_STATUS - ori k0, k0, ST0_EXL + ori k0, k0, ST0_EXL li k1, ~(ST0_BEV | ST0_ERL) - and k0, k0, k1 - mtc0 k0, CP0_STATUS + and k0, k0, k1 + mtc0 k0, CP0_STATUS _ehb SAVE_ALL move a0, sp @@ -396,7 +396,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .macro __BUILD_count exception LONG_L t0,exception_count_\exception - LONG_ADDIU t0, 1 + LONG_ADDIU t0, 1 LONG_S t0,exception_count_\exception .comm exception_count\exception, 8, 8 .endm @@ -457,8 +457,8 @@ NESTED(nmi_handler, PT_SIZE, sp) MFC0 k1, CP0_ENTRYHI andi k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX MFC0 k0, CP0_EPC - PTR_SRL k0, _PAGE_SHIFT + 1 - PTR_SLL k0, _PAGE_SHIFT + 1 + PTR_SRL k0, _PAGE_SHIFT + 1 + PTR_SLL k0, _PAGE_SHIFT + 1 or k1, k0 MTC0 k1, CP0_ENTRYHI mtc0_tlbw_hazard @@ -478,27 +478,27 @@ NESTED(nmi_handler, PT_SIZE, sp) /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */ MFC0 k1, CP0_EPC #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2) - and k0, k1, 1 - beqz k0, 1f - xor k1, k0 - lhu k0, (k1) - lhu k1, 2(k1) - ins k1, k0, 16, 16 - lui k0, 0x007d - b docheck - ori k0, 0x6b3c + and k0, k1, 1 + beqz k0, 1f + xor k1, k0 + lhu k0, (k1) + lhu k1, 2(k1) + ins k1, k0, 16, 16 + lui k0, 0x007d + b docheck + ori k0, 0x6b3c 1: - lui k0, 0x7c03 - lw k1, (k1) - ori k0, 0xe83b + lui k0, 0x7c03 + lw k1, (k1) + ori k0, 0xe83b #else - andi k0, k1, 1 - bnez k0, handle_ri - lui k0, 0x7c03 - lw k1, (k1) - ori k0, 0xe83b + andi k0, k1, 1 + bnez k0, handle_ri + lui k0, 0x7c03 + lw k1, (k1) + ori k0, 0xe83b #endif - .set reorder + .set reorder docheck: bne k0, k1, handle_ri /* if not ours */ -- cgit v1.2.3-59-g8ed1b From e54ad8c56258af3b414a3e5707a45c18f1db69e1 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 28 Apr 2016 11:03:08 +0200 Subject: MIPS: Don't add leading spacing to command lines The leading spaces don't affect functionality but are unnecessary. Signed-off-by: Rabin Vincent Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13180/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 693e8d1a174c..38815f78c819 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -673,13 +673,15 @@ static void __init arch_mem_init(char **cmdline_p) strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); if (EXTEND_WITH_PROM && arcs_cmdline[0]) { - strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + if (boot_command_line[0]) + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); } #if defined(CONFIG_CMDLINE_BOOL) if (builtin_cmdline[0]) { - strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + if (boot_command_line[0]) + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); } #endif -- cgit v1.2.3-59-g8ed1b From ed47e1533292e26baaec1b5ed7d425690289d5df Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 28 Apr 2016 11:03:09 +0200 Subject: MIPS: Add support for extending builtin cmdline Allow the builtin command line to be extended by what the bootloader passes in. For example, the bootloader can pass specific arguments depending on the boot mode, and these should override the defaults in the builtin cmdline. The default MIPS_CMDLINE_FROM_BOOTLOADER option prepends the bootloader's cmdline to the builtin cmdline so is not suitable for this purpose. Signed-off-by: Rabin Vincent Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13181/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 4 ++++ arch/mips/kernel/setup.c | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5cc5b621ae69..d10ed57ad418 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2930,6 +2930,10 @@ choice config MIPS_CMDLINE_FROM_BOOTLOADER bool "Bootloader kernel arguments if available" + + config MIPS_CMDLINE_BUILTIN_EXTEND + depends on CMDLINE_BOOL + bool "Extend builtin kernel arguments with bootloader arguments" endchoice endmenu diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 38815f78c819..19c03a9e7492 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -640,6 +640,8 @@ static void __init request_crashkernel(struct resource *res) #define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER) #define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB) #define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND) +#define BUILTIN_EXTEND_WITH_PROM \ + IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND) static void __init arch_mem_init(char **cmdline_p) { @@ -684,6 +686,12 @@ static void __init arch_mem_init(char **cmdline_p) strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); } + + if (BUILTIN_EXTEND_WITH_PROM && arcs_cmdline[0]) { + if (boot_command_line[0]) + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); + } #endif #endif strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); -- cgit v1.2.3-59-g8ed1b From 93583e178ebfdd2fadf950eef1547f305cac12ca Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:45 +0100 Subject: MIPS: math-emu: Fix BC1{EQ,NE}Z emulation The conditions for branching when emulating the BC1EQZ & BC1NEZ instructions were backwards, leading to each of those instructions being treated as the other. Fix this by reversing the conditions, and clear up the code a little for readability & checkpatch. Fixes: c909ca718e8f ("MIPS: math-emu: Emulate missing BC1{EQ,NE}Z instructions") Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13150/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index cdfd44ffa51c..99977c3bf10a 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -973,9 +973,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, struct mm_decoded_insn dec_insn, void *__user *fault_addr) { unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc; - unsigned int cond, cbit; + unsigned int cond, cbit, bit0; mips_instruction ir; int likely, pc_inc; + union fpureg *fpr; u32 __user *wva; u64 __user *dva; u32 wval; @@ -1187,14 +1188,14 @@ emul: return SIGILL; cond = likely = 0; + fpr = ¤t->thread.fpu.fpr[MIPSInst_RT(ir)]; + bit0 = get_fpr32(fpr, 0) & 0x1; switch (MIPSInst_RS(ir)) { case bc1eqz_op: - if (get_fpr32(¤t->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1) - cond = 1; + cond = bit0 == 0; break; case bc1nez_op: - if (!(get_fpr32(¤t->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1)) - cond = 1; + cond = bit0 != 0; break; } goto branch_common; -- cgit v1.2.3-59-g8ed1b From ac1496980f1d2752f26769f5db63afbc9ac2b603 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:46 +0100 Subject: MIPS: Fix BC1{EQ,NE}Z return offset calculation The conditions for branching when emulating the BC1EQZ & BC1NEZ instructions were backwards, leading to each of those instructions being treated as the other. Fix this by reversing the conditions, and clear up the code a little for readability & checkpatch. Fixes: c8a34581ec09 ("MIPS: Emulate the BC1{EQ,NE}Z FPU instructions") Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13151/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/branch.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index d8f9b357b222..ceca6cc41b2b 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -688,21 +688,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, } lose_fpu(1); /* Save FPU state for the emulator. */ reg = insn.i_format.rt; - bit = 0; - switch (insn.i_format.rs) { - case bc1eqz_op: - /* Test bit 0 */ - if (get_fpr32(¤t->thread.fpu.fpr[reg], 0) - & 0x1) - bit = 1; - break; - case bc1nez_op: - /* Test bit 0 */ - if (!(get_fpr32(¤t->thread.fpu.fpr[reg], 0) - & 0x1)) - bit = 1; - break; - } + bit = get_fpr32(¤t->thread.fpu.fpr[reg], 0) & 0x1; + if (insn.i_format.rs == bc1eqz_op) + bit = !bit; own_fpu(1); if (bit) epc = epc + 4 + -- cgit v1.2.3-59-g8ed1b From b6d5c4eda7a771e72b3640500e026d72c4f64419 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:47 +0100 Subject: MIPS: inst: Declare fsel_op for sel.fmt instruction Declare the opcode for the MIPSr6 sel.fmt instruction, as fsel_op in order to match other FP op names. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13152/ Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/inst.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 3bb8cd957e81..8051f9aa1379 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -167,6 +167,7 @@ enum cop1_sdw_func { fceill_op = 0x0a, ffloorl_op = 0x0b, fround_op = 0x0c, ftrunc_op = 0x0d, fceil_op = 0x0e, ffloor_op = 0x0f, + fsel_op = 0x10, fmovc_op = 0x11, fmovz_op = 0x12, fmovn_op = 0x13, fseleqz_op = 0x14, frecip_op = 0x15, frsqrt_op = 0x16, -- cgit v1.2.3-59-g8ed1b From 4b820d95dc53c15e6e727da964430a3ed60e05ef Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:48 +0100 Subject: MIPS: math-emu: Emulate MIPSr6 sel.fmt instruction Add support for emulating the MIPSr6 sel.fmt instruction, which was previously missing from the FPU emulation code. This instruction selects its result from 2 possible source registers, based upon bit 0 of the destination register, and is valid only for S (single) & D (double) data types. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13153/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 99977c3bf10a..85dd17497151 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1675,7 +1675,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, union ieee754sp(*b) (union ieee754sp, union ieee754sp); union ieee754sp(*u) (union ieee754sp); } handler; - union ieee754sp fs, ft; + union ieee754sp fd, fs, ft; switch (MIPSInst_FUNC(ir)) { /* binary ops */ @@ -1946,6 +1946,17 @@ copcsr: rfmt = w_fmt; goto copcsr; + case fsel_op: + if (!cpu_has_mips_r6) + return SIGILL; + + SPFROMREG(fd, MIPSInst_FD(ir)); + if (fd.bits & 0x1) + SPFROMREG(rv.s, MIPSInst_FT(ir)); + else + SPFROMREG(rv.s, MIPSInst_FS(ir)); + break; + case fcvtl_op: if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; @@ -1994,7 +2005,7 @@ copcsr: } case d_fmt: { - union ieee754dp fs, ft; + union ieee754dp fd, fs, ft; union { union ieee754dp(*b) (union ieee754dp, union ieee754dp); union ieee754dp(*u) (union ieee754dp); @@ -2244,6 +2255,17 @@ dcopuop: rfmt = w_fmt; goto copcsr; + case fsel_op: + if (!cpu_has_mips_r6) + return SIGILL; + + DPFROMREG(fd, MIPSInst_FD(ir)); + if (fd.bits & 0x1) + DPFROMREG(rv.d, MIPSInst_FT(ir)); + else + DPFROMREG(rv.d, MIPSInst_FS(ir)); + break; + case fcvtl_op: if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; -- cgit v1.2.3-59-g8ed1b From 6162051e87f6ea785cb51ad99bdcf8eb0bd9cb07 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:49 +0100 Subject: MIPS: math-emu: Unify ieee754sp_m{add,sub}f The code for emulating MIPSr6 madd.s & msub.s instructions has previously been implemented as 2 different functions, namely ieee754sp_maddf & ieee754sp_msubf. The difference in behaviour of these 2 instructions is merely the sign of the product, so we can easily share the code implementing them. Do this for the single precision variant, removing the original ieee754sp_msubf in favor of reusing the code from ieee754sp_maddf. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13154/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/Makefile | 2 +- arch/mips/math-emu/sp_maddf.c | 22 +++- arch/mips/math-emu/sp_msubf.c | 258 ------------------------------------------ 3 files changed, 21 insertions(+), 261 deletions(-) delete mode 100644 arch/mips/math-emu/sp_msubf.c (limited to 'arch') diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index a19641d3ac23..3389aff21783 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -6,7 +6,7 @@ obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \ dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \ dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \ sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \ - sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o sp_fmin.o sp_fmax.o \ + sp_tint.o sp_fint.o sp_maddf.o sp_2008class.o sp_fmin.o sp_fmax.o \ dsemul.o lib-y += ieee754d.o \ diff --git a/arch/mips/math-emu/sp_maddf.c b/arch/mips/math-emu/sp_maddf.c index dd1dd83e34eb..93b7132d60e2 100644 --- a/arch/mips/math-emu/sp_maddf.c +++ b/arch/mips/math-emu/sp_maddf.c @@ -14,8 +14,12 @@ #include "ieee754sp.h" -union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x, - union ieee754sp y) +enum maddf_flags { + maddf_negate_product = 1 << 0, +}; + +static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, + union ieee754sp y, enum maddf_flags flags) { int re; int rs; @@ -154,6 +158,8 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x, re = xe + ye; rs = xs ^ ys; + if (flags & maddf_negate_product) + rs ^= 1; /* shunt to top of word */ xm <<= 32 - (SP_FBITS + 1); @@ -253,3 +259,15 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x, } return ieee754sp_format(zs, ze, zm); } + +union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x, + union ieee754sp y) +{ + return _sp_maddf(z, x, y, 0); +} + +union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x, + union ieee754sp y) +{ + return _sp_maddf(z, x, y, maddf_negate_product); +} diff --git a/arch/mips/math-emu/sp_msubf.c b/arch/mips/math-emu/sp_msubf.c deleted file mode 100644 index 81c38b980d69..000000000000 --- a/arch/mips/math-emu/sp_msubf.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * IEEE754 floating point arithmetic - * single precision: MSUB.f (Fused Multiply Subtract) - * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft]) - * - * MIPS floating point support - * Copyright (C) 2015 Imagination Technologies, Ltd. - * Author: Markos Chandras - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2 of the License. - */ - -#include "ieee754sp.h" - -union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x, - union ieee754sp y) -{ - int re; - int rs; - unsigned rm; - unsigned short lxm; - unsigned short hxm; - unsigned short lym; - unsigned short hym; - unsigned lrm; - unsigned hrm; - unsigned t; - unsigned at; - int s; - - COMPXSP; - COMPYSP; - u32 zm; int ze; int zs __maybe_unused; int zc; - - EXPLODEXSP; - EXPLODEYSP; - EXPLODESP(z, zc, zs, ze, zm) - - FLUSHXSP; - FLUSHYSP; - FLUSHSP(z, zc, zs, ze, zm); - - ieee754_clearcx(); - - switch (zc) { - case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(z); - case IEEE754_CLASS_DNORM: - SPDNORMx(zm, ze); - /* QNAN is handled separately below */ - } - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - /* - * Infinity handling - */ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - if (zc == IEEE754_CLASS_QNAN) - return z; - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_indef(); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (zc == IEEE754_CLASS_QNAN) - return z; - return ieee754sp_inf(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - if (zc == IEEE754_CLASS_INF) - return ieee754sp_inf(zs); - /* Multiplication is 0 so just return z */ - return z; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754sp_inf(zs); - SPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754sp_inf(zs); - SPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754sp_inf(zs); - /* fall through to real compuation */ - } - - /* Finally get to do some computation */ - - /* - * Do the multiplication bit first - * - * rm = xm * ym, re = xe + ye basically - * - * At this point xm and ym should have been normalized. - */ - - /* rm = xm * ym, re = xe+ye basically */ - assert(xm & SP_HIDDEN_BIT); - assert(ym & SP_HIDDEN_BIT); - - re = xe + ye; - rs = xs ^ ys; - - /* shunt to top of word */ - xm <<= 32 - (SP_FBITS + 1); - ym <<= 32 - (SP_FBITS + 1); - - /* - * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. - */ - lxm = xm & 0xffff; - hxm = xm >> 16; - lym = ym & 0xffff; - hym = ym >> 16; - - lrm = lxm * lym; /* 16 * 16 => 32 */ - hrm = hxm * hym; /* 16 * 16 => 32 */ - - t = lxm * hym; /* 16 * 16 => 32 */ - at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - hrm = hrm + (t >> 16); - - t = hxm * lym; /* 16 * 16 => 32 */ - at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - hrm = hrm + (t >> 16); - - rm = hrm | (lrm != 0); - - /* - * Sticky shift down to normal rounding precision. - */ - if ((int) rm < 0) { - rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | - ((rm << (SP_FBITS + 1 + 3)) != 0); - re++; - } else { - rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | - ((rm << (SP_FBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (SP_HIDDEN_BIT << 3)); - - /* And now the subtraction */ - - /* Flip sign of r and handle as add */ - rs ^= 1; - - assert(zm & SP_HIDDEN_BIT); - - /* - * Provide guard,round and stick bit space. - */ - zm <<= 3; - - if (ze > re) { - /* - * Have to shift y fraction right to align. - */ - s = ze - re; - SPXSRSYn(s); - } else if (re > ze) { - /* - * Have to shift x fraction right to align. - */ - s = re - ze; - SPXSRSYn(s); - } - assert(ze == re); - assert(ze <= SP_EMAX); - - if (zs == rs) { - /* - * Generate 28 bit result of adding two 27 bit numbers - * leaving result in zm, zs and ze. - */ - zm = zm + rm; - - if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */ - SPXSRSX1(); /* shift preserving sticky */ - } - } else { - if (zm >= rm) { - zm = zm - rm; - } else { - zm = rm - zm; - zs = rs; - } - if (zm == 0) - return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); - - /* - * Normalize in extended single precision - */ - while ((zm >> (SP_MBITS + 3)) == 0) { - zm <<= 1; - ze--; - } - - } - return ieee754sp_format(zs, ze, zm); -} -- cgit v1.2.3-59-g8ed1b From d728f6709bcc49c98097485e3561f1faaf52b4f3 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:50 +0100 Subject: MIPS: math-emu: Unify ieee754dp_m{add,sub}f The code for emulating MIPSr6 madd.d & msub.d instructions has previously been implemented as 2 different functions, namely ieee754dp_maddf & ieee754dp_msubf. The difference in behaviour of these 2 instructions is merely the sign of the product, so we can easily share the code implementing them. Do this for the double precision variant, removing the original ieee754dp_msubf in favor of reusing the code from ieee754dp_maddf. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13155/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/Makefile | 2 +- arch/mips/math-emu/dp_maddf.c | 22 +++- arch/mips/math-emu/dp_msubf.c | 269 ------------------------------------------ 3 files changed, 21 insertions(+), 272 deletions(-) delete mode 100644 arch/mips/math-emu/dp_msubf.c (limited to 'arch') diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 3389aff21783..e9bbc2a6526f 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -4,7 +4,7 @@ obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \ dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \ - dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \ + dp_tint.o dp_fint.o dp_maddf.o dp_2008class.o dp_fmin.o dp_fmax.o \ sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \ sp_tint.o sp_fint.o sp_maddf.o sp_2008class.o sp_fmin.o sp_fmax.o \ dsemul.o diff --git a/arch/mips/math-emu/dp_maddf.c b/arch/mips/math-emu/dp_maddf.c index 119eda9fa1ea..d5e0fb13ef0f 100644 --- a/arch/mips/math-emu/dp_maddf.c +++ b/arch/mips/math-emu/dp_maddf.c @@ -14,8 +14,12 @@ #include "ieee754dp.h" -union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x, - union ieee754dp y) +enum maddf_flags { + maddf_negate_product = 1 << 0, +}; + +static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, + union ieee754dp y, enum maddf_flags flags) { int re; int rs; @@ -154,6 +158,8 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x, re = xe + ye; rs = xs ^ ys; + if (flags & maddf_negate_product) + rs ^= 1; /* shunt to top of word */ xm <<= 64 - (DP_FBITS + 1); @@ -263,3 +269,15 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x, return ieee754dp_format(zs, ze, zm); } + +union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x, + union ieee754dp y) +{ + return _dp_maddf(z, x, y, 0); +} + +union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x, + union ieee754dp y) +{ + return _dp_maddf(z, x, y, maddf_negate_product); +} diff --git a/arch/mips/math-emu/dp_msubf.c b/arch/mips/math-emu/dp_msubf.c deleted file mode 100644 index 12241262f856..000000000000 --- a/arch/mips/math-emu/dp_msubf.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * IEEE754 floating point arithmetic - * double precision: MSUB.f (Fused Multiply Subtract) - * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft]) - * - * MIPS floating point support - * Copyright (C) 2015 Imagination Technologies, Ltd. - * Author: Markos Chandras - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2 of the License. - */ - -#include "ieee754dp.h" - -union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x, - union ieee754dp y) -{ - int re; - int rs; - u64 rm; - unsigned lxm; - unsigned hxm; - unsigned lym; - unsigned hym; - u64 lrm; - u64 hrm; - u64 t; - u64 at; - int s; - - COMPXDP; - COMPYDP; - - u64 zm; int ze; int zs __maybe_unused; int zc; - - EXPLODEXDP; - EXPLODEYDP; - EXPLODEDP(z, zc, zs, ze, zm) - - FLUSHXDP; - FLUSHYDP; - FLUSHDP(z, zc, zs, ze, zm); - - ieee754_clearcx(); - - switch (zc) { - case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(z); - case IEEE754_CLASS_DNORM: - DPDNORMx(zm, ze); - /* QNAN is handled separately below */ - } - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* - * Infinity handling - */ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - if (zc == IEEE754_CLASS_QNAN) - return z; - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_indef(); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (zc == IEEE754_CLASS_QNAN) - return z; - return ieee754dp_inf(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - if (zc == IEEE754_CLASS_INF) - return ieee754dp_inf(zs); - /* Multiplication is 0 so just return z */ - return z; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754dp_inf(zs); - DPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754dp_inf(zs); - DPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - if (zc == IEEE754_CLASS_QNAN) - return z; - else if (zc == IEEE754_CLASS_INF) - return ieee754dp_inf(zs); - /* fall through to real computations */ - } - - /* Finally get to do some computation */ - - /* - * Do the multiplication bit first - * - * rm = xm * ym, re = xe + ye basically - * - * At this point xm and ym should have been normalized. - */ - assert(xm & DP_HIDDEN_BIT); - assert(ym & DP_HIDDEN_BIT); - - re = xe + ye; - rs = xs ^ ys; - - /* shunt to top of word */ - xm <<= 64 - (DP_FBITS + 1); - ym <<= 64 - (DP_FBITS + 1); - - /* - * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. - */ - - /* 32 * 32 => 64 */ -#define DPXMULT(x, y) ((u64)(x) * (u64)y) - - lxm = xm; - hxm = xm >> 32; - lym = ym; - hym = ym >> 32; - - lrm = DPXMULT(lxm, lym); - hrm = DPXMULT(hxm, hym); - - t = DPXMULT(lxm, hym); - - at = lrm + (t << 32); - hrm += at < lrm; - lrm = at; - - hrm = hrm + (t >> 32); - - t = DPXMULT(hxm, lym); - - at = lrm + (t << 32); - hrm += at < lrm; - lrm = at; - - hrm = hrm + (t >> 32); - - rm = hrm | (lrm != 0); - - /* - * Sticky shift down to normal rounding precision. - */ - if ((s64) rm < 0) { - rm = (rm >> (64 - (DP_FBITS + 1 + 3))) | - ((rm << (DP_FBITS + 1 + 3)) != 0); - re++; - } else { - rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | - ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (DP_HIDDEN_BIT << 3)); - - /* And now the subtraction */ - - /* flip sign of r and handle as add */ - rs ^= 1; - - assert(zm & DP_HIDDEN_BIT); - - /* - * Provide guard,round and stick bit space. - */ - zm <<= 3; - - if (ze > re) { - /* - * Have to shift y fraction right to align. - */ - s = ze - re; - rm = XDPSRS(rm, s); - re += s; - } else if (re > ze) { - /* - * Have to shift x fraction right to align. - */ - s = re - ze; - zm = XDPSRS(zm, s); - ze += s; - } - assert(ze == re); - assert(ze <= DP_EMAX); - - if (zs == rs) { - /* - * Generate 28 bit result of adding two 27 bit numbers - * leaving result in xm, xs and xe. - */ - zm = zm + rm; - - if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */ - zm = XDPSRS1(zm); - ze++; - } - } else { - if (zm >= rm) { - zm = zm - rm; - } else { - zm = rm - zm; - zs = rs; - } - if (zm == 0) - return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); - - /* - * Normalize to rounding precision. - */ - while ((zm >> (DP_FBITS + 3)) == 0) { - zm <<= 1; - ze--; - } - } - - return ieee754dp_format(zs, ze, zm); -} -- cgit v1.2.3-59-g8ed1b From e2d11e1a8398b7447d337add50521a5abc6267fd Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:51 +0100 Subject: MIPS: math-emu: Add z argument macros Introduce macros for handling the "z" argument to maddf & msubf, making its handling consistent with that of the "x" & "y" arguments rather than open-coding equivalents. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13156/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/dp_maddf.c | 9 ++++----- arch/mips/math-emu/ieee754dp.h | 1 + arch/mips/math-emu/ieee754int.h | 10 ++++++++++ arch/mips/math-emu/ieee754sp.h | 1 + arch/mips/math-emu/sp_maddf.c | 8 ++++---- 5 files changed, 20 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/dp_maddf.c b/arch/mips/math-emu/dp_maddf.c index d5e0fb13ef0f..0e1d4d80e22e 100644 --- a/arch/mips/math-emu/dp_maddf.c +++ b/arch/mips/math-emu/dp_maddf.c @@ -36,16 +36,15 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, COMPXDP; COMPYDP; - - u64 zm; int ze; int zs __maybe_unused; int zc; + COMPZDP; EXPLODEXDP; EXPLODEYDP; - EXPLODEDP(z, zc, zs, ze, zm) + EXPLODEZDP; FLUSHXDP; FLUSHYDP; - FLUSHDP(z, zc, zs, ze, zm); + FLUSHZDP; ieee754_clearcx(); @@ -54,7 +53,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(z); case IEEE754_CLASS_DNORM: - DPDNORMx(zm, ze); + DPDNORMZ; /* QNAN is handled separately below */ } diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index e2babd98fee3..9ba023004eb6 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -60,6 +60,7 @@ static inline int ieee754dp_finite(union ieee754dp x) while ((m >> DP_FBITS) == 0) { m <<= 1; e--; } #define DPDNORMX DPDNORMx(xm, xe) #define DPDNORMY DPDNORMx(ym, ye) +#define DPDNORMZ DPDNORMx(zm, ze) static inline union ieee754dp builddp(int s, int bx, u64 m) { diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index ed7bb277b3e0..8bc2f6963324 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -55,6 +55,9 @@ static inline int ieee754_class_nan(int xc) #define COMPYSP \ unsigned ym; int ye; int ys; int yc +#define COMPZSP \ + unsigned zm; int ze; int zs; int zc + #define EXPLODESP(v, vc, vs, ve, vm) \ { \ vs = SPSIGN(v); \ @@ -81,6 +84,7 @@ static inline int ieee754_class_nan(int xc) } #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm) #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym) +#define EXPLODEZSP EXPLODESP(z, zc, zs, ze, zm) #define COMPXDP \ @@ -89,6 +93,9 @@ static inline int ieee754_class_nan(int xc) #define COMPYDP \ u64 ym; int ye; int ys; int yc +#define COMPZDP \ + u64 zm; int ze; int zs; int zc + #define EXPLODEDP(v, vc, vs, ve, vm) \ { \ vm = DPMANT(v); \ @@ -115,6 +122,7 @@ static inline int ieee754_class_nan(int xc) } #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm) #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym) +#define EXPLODEZDP EXPLODEDP(z, zc, zs, ze, zm) #define FLUSHDP(v, vc, vs, ve, vm) \ if (vc==IEEE754_CLASS_DNORM) { \ @@ -140,7 +148,9 @@ static inline int ieee754_class_nan(int xc) #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm) #define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym) +#define FLUSHZDP FLUSHDP(z, zc, zs, ze, zm) #define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm) #define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym) +#define FLUSHZSP FLUSHSP(z, zc, zs, ze, zm) #endif /* __IEEE754INT_H */ diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 374a3f00a589..b24fdff90f21 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -65,6 +65,7 @@ static inline int ieee754sp_finite(union ieee754sp x) while ((m >> SP_FBITS) == 0) { m <<= 1; e--; } #define SPDNORMX SPDNORMx(xm, xe) #define SPDNORMY SPDNORMx(ym, ye) +#define SPDNORMZ SPDNORMx(zm, ze) static inline union ieee754sp buildsp(int s, int bx, unsigned m) { diff --git a/arch/mips/math-emu/sp_maddf.c b/arch/mips/math-emu/sp_maddf.c index 93b7132d60e2..86e1d0b25446 100644 --- a/arch/mips/math-emu/sp_maddf.c +++ b/arch/mips/math-emu/sp_maddf.c @@ -36,15 +36,15 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, COMPXSP; COMPYSP; - u32 zm; int ze; int zs __maybe_unused; int zc; + COMPZSP; EXPLODEXSP; EXPLODEYSP; - EXPLODESP(z, zc, zs, ze, zm) + EXPLODEZSP; FLUSHXSP; FLUSHYSP; - FLUSHSP(z, zc, zs, ze, zm); + FLUSHZSP; ieee754_clearcx(); @@ -53,7 +53,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(z); case IEEE754_CLASS_DNORM: - SPDNORMx(zm, ze); + SPDNORMZ; /* QNAN is handled separately below */ } -- cgit v1.2.3-59-g8ed1b From 95bff2410cdccfe2cf4b99f4e86165956767740e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:52 +0100 Subject: MIPS: math-emu: Fix bit-width in ieee754dp_{mul, maddf, msubf} comments A comment in ieee754dp_mul indicates that the code is about to perform a 32b x 32b multiplication & keep the high 32b of the result. It appears this was copied from the single-precision multiplication code, since the code actually goes on to perform a 64b x 64b multiplication & keep the high 64b of the result. Fix the comment to indicate 64b. It appears also that this comment was copied verbatim along with the rest of the multiplication code into ieee754dp_maddf, which has since been renamed _dp_maddf. Fix the same issue there. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13157/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/dp_maddf.c | 2 +- arch/mips/math-emu/dp_mul.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/dp_maddf.c b/arch/mips/math-emu/dp_maddf.c index 0e1d4d80e22e..dc83fdd43f60 100644 --- a/arch/mips/math-emu/dp_maddf.c +++ b/arch/mips/math-emu/dp_maddf.c @@ -165,7 +165,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, ym <<= 64 - (DP_FBITS + 1); /* - * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. + * Multiply 64 bits xm, ym to give high 64 bits rm with stickness. */ /* 32 * 32 => 64 */ diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index d0901f03fa19..d6a7573d2c52 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -125,7 +125,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) ym <<= 64 - (DP_FBITS + 1); /* - * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. + * Multiply 64 bits xm, ym to give high 64 bits rm with stickness. */ /* 32 * 32 => 64 */ -- cgit v1.2.3-59-g8ed1b From 5c18c936b52ae80db5737849e11f436e79b84b2d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:53 +0100 Subject: MIPS: math-emu: Fix code indentation A line incrementing the re variable was indented a level too deep in ieee754dp_mul, making the code unclear to read. Fix the indentation. This appears to have been copied verbatim along with the rest of the multiplication code to ieee754dp_maddf, now _dp_maddf, too so fix the indentation there too. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13158/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/dp_maddf.c | 2 +- arch/mips/math-emu/dp_mul.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/dp_maddf.c b/arch/mips/math-emu/dp_maddf.c index dc83fdd43f60..4a2d03c72959 100644 --- a/arch/mips/math-emu/dp_maddf.c +++ b/arch/mips/math-emu/dp_maddf.c @@ -203,7 +203,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, if ((s64) rm < 0) { rm = (rm >> (64 - (DP_FBITS + 1 + 3))) | ((rm << (DP_FBITS + 1 + 3)) != 0); - re++; + re++; } else { rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index d6a7573d2c52..87d0b44b0614 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -163,7 +163,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) if ((s64) rm < 0) { rm = (rm >> (64 - (DP_FBITS + 1 + 3))) | ((rm << (DP_FBITS + 1 + 3)) != 0); - re++; + re++; } else { rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); -- cgit v1.2.3-59-g8ed1b From db57f29d50683afd75c7f8b9908af7669837c3a9 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:54 +0100 Subject: MIPS: math-emu: Fix m{add,sub}.s shifts The code in _sp_maddf (formerly ieee754sp_madd) appears to have been copied verbatim from ieee754sp_add, and although it's adding the unpacked "r" & "z" floats it kept using macros that operate on "x" & "y". This led to the addition being carried out incorrectly on some mismash of the product, accumulator & multiplicand fields. Typically this would lead to the assertions "ze == re" & "ze <= SP_EMAX" failing since ze & re hadn't been operated upon. Signed-off-by: Paul Burton Fixes: e24c3bec3e8e ("MIPS: math-emu: Add support for the MIPS R6 MADDF FPU instruction") Cc: Adam Buchbinder Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13159/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/ieee754sp.c | 3 ++- arch/mips/math-emu/ieee754sp.h | 16 +++++++--------- arch/mips/math-emu/sp_add.c | 6 ++++-- arch/mips/math-emu/sp_maddf.c | 13 ++++++++----- arch/mips/math-emu/sp_sub.c | 6 ++++-- 5 files changed, 25 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 860e9162097f..260e68965907 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -141,7 +141,8 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) } else { /* sticky right shift es bits */ - SPXSRSXn(es); + xm = XSPSRS(xm, es); + xe += es; assert((xm & (SP_HIDDEN_BIT << 3)) == 0); assert(xe == SP_EMIN); } diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index b24fdff90f21..8476067075fe 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -46,19 +46,17 @@ static inline int ieee754sp_finite(union ieee754sp x) } /* 3bit extended single precision sticky right shift */ -#define SPXSRSXn(rs) \ - (xe += rs, \ - xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) +#define XSPSRS(v, rs) \ + ((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0)) -#define SPXSRSX1() \ - (xe++, (xm = (xm >> 1) | (xm & 1))) +#define XSPSRS1(m) \ + ((m >> 1) | (m & 1)) -#define SPXSRSYn(rs) \ - (ye+=rs, \ - ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) +#define SPXSRSX1() \ + (xe++, (xm = XSPSRS1(xm))) #define SPXSRSY1() \ - (ye++, (ym = (ym >> 1) | (ym & 1))) + (ye++, (ym = XSPSRS1(ym))) /* convert denormal to normalized with extended exponent */ #define SPDNORMx(m,e) \ diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index f1c87b07d3b4..c55c0c00bca8 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -132,13 +132,15 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) * Have to shift y fraction right to align. */ s = xe - ye; - SPXSRSYn(s); + ym = XSPSRS(ym, s); + ye += s; } else if (ye > xe) { /* * Have to shift x fraction right to align. */ s = ye - xe; - SPXSRSXn(s); + xm = XSPSRS(xm, s); + xe += s; } assert(xe == ye); assert(xe <= SP_EMAX); diff --git a/arch/mips/math-emu/sp_maddf.c b/arch/mips/math-emu/sp_maddf.c index 86e1d0b25446..a8cd8b4f235e 100644 --- a/arch/mips/math-emu/sp_maddf.c +++ b/arch/mips/math-emu/sp_maddf.c @@ -214,16 +214,18 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, if (ze > re) { /* - * Have to shift y fraction right to align. + * Have to shift r fraction right to align. */ s = ze - re; - SPXSRSYn(s); + rm = XSPSRS(rm, s); + re += s; } else if (re > ze) { /* - * Have to shift x fraction right to align. + * Have to shift z fraction right to align. */ s = re - ze; - SPXSRSYn(s); + zm = XSPSRS(zm, s); + ze += s; } assert(ze == re); assert(ze <= SP_EMAX); @@ -236,7 +238,8 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, zm = zm + rm; if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */ - SPXSRSX1(); + zm = XSPSRS1(zm); + ze++; } } else { if (zm >= rm) { diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index ec5f937a8b3e..dc998ed47295 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -134,13 +134,15 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) * have to shift y fraction right to align */ s = xe - ye; - SPXSRSYn(s); + ym = XSPSRS(ym, s); + ye += s; } else if (ye > xe) { /* * have to shift x fraction right to align */ s = ye - xe; - SPXSRSXn(s); + xm = XSPSRS(xm, s); + xe += s; } assert(xe == ye); assert(xe <= SP_EMAX); -- cgit v1.2.3-59-g8ed1b From ab4a92e66741b35ca12f8497896bafbe579c28a1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 14:04:55 +0100 Subject: MIPS: math-emu: Fix jalr emulation when rd == $0 When emulating a jalr instruction with rd == $0, the code in isBranchInstr was incorrectly writing to GPR $0 which should actually always remain zeroed. This would lead to any further instructions emulated which use $0 operating on a bogus value until the task is next context switched, at which point the value of $0 in the task context would be restored to the correct zero by a store in SAVE_SOME. Fix this by not writing to rd if it is $0. Fixes: 102cedc32a6e ("MIPS: microMIPS: Floating point support.") Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: stable # v3.10 Patchwork: https://patchwork.linux-mips.org/patch/13160/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 85dd17497151..d96e912b9d44 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -445,9 +445,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, case spec_op: switch (insn.r_format.func) { case jalr_op: - regs->regs[insn.r_format.rd] = - regs->cp0_epc + dec_insn.pc_inc + - dec_insn.next_pc_inc; + if (insn.r_format.rd != 0) { + regs->regs[insn.r_format.rd] = + regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + } /* Fall through */ case jr_op: /* For R6, JR already emulated in jalr_op */ -- cgit v1.2.3-59-g8ed1b From 12822570a29bdc12c69fca2c021753cb5ce319c5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 19 Apr 2016 09:24:59 +0100 Subject: MIPS: Separate XPA CPU feature into LPA and MVH XPA (eXtended Physical Addressing) should be detected as a combination of two architectural features: - Large Physical Address (as per Config3.LPA). With XPA this will be set on MIPS32r5 cores, but it may also be set for MIPS64r2 cores too. - MTHC0/MFHC0 instructions (as per Config5.MVH). With XPA this will be set, but it may also be set in VZ guest context even when Config3.LPA in the guest context has been cleared by the hypervisor. As such, XPA is only usable if both bits are set. Update CPU features to separate these two features, with cpu_has_xpa requiring both to be set. Signed-off-by: James Hogan Cc: Paul Burton Cc: Maciej W. Rozycki Cc: Joshua Kinard Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13112/ Signed-off-by: Paul Burton Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 8 +++++++- arch/mips/include/asm/cpu.h | 3 ++- arch/mips/kernel/cpu-probe.c | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index da92d513a395..bff73c52b273 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -145,8 +145,14 @@ # endif #endif +#ifndef cpu_has_lpa +#define cpu_has_lpa (cpu_data[0].options & MIPS_CPU_LPA) +#endif +#ifndef cpu_has_mvh +#define cpu_has_mvh (cpu_data[0].options & MIPS_CPU_MVH) +#endif #ifndef cpu_has_xpa -#define cpu_has_xpa (cpu_data[0].options & MIPS_CPU_XPA) +#define cpu_has_xpa (cpu_has_lpa && cpu_has_mvh) #endif #ifndef cpu_has_vtag_icache #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index d9150a210df6..f6cecc52a8c6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -394,7 +394,7 @@ enum cpu_type_enum { #define MIPS_CPU_MAAR MBIT_ULL(30) /* MAAR(I) registers are present */ #define MIPS_CPU_FRE MBIT_ULL(31) /* FRE & UFE bits implemented */ #define MIPS_CPU_RW_LLB MBIT_ULL(32) /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA MBIT_ULL(33) /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_LPA MBIT_ULL(33) /* CPU supports Large Physical Addressing */ #define MIPS_CPU_CDMM MBIT_ULL(34) /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST MBIT_ULL(35) /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP MBIT_ULL(36) /* Small (1KB) page support */ @@ -403,6 +403,7 @@ enum cpu_type_enum { #define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ +#define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5ca4fefb1344..8eda42a9ca59 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -702,6 +702,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_VINT; if (config3 & MIPS_CONF3_VEIC) c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_LPA) + c->options |= MIPS_CPU_LPA; if (config3 & MIPS_CONF3_MT) c->ases |= MIPS_ASE_MIPSMT; if (config3 & MIPS_CONF3_ULRI) -- cgit v1.2.3-59-g8ed1b From 14bc241443e126c62fcbf571b7d4c79740debc58 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 19 Apr 2016 09:25:00 +0100 Subject: MIPS: Fix HTW config on XPA kernel without LPA enabled The hardware page table walker (HTW) configuration is broken on XPA kernels where XPA couldn't be enabled (either nohtw or the hardware doesn't support it). This is because the PWSize.PTEW field (PTE width) was only set to 8 bytes (an extra shift of 1) in config_htw_params() if PageGrain.ELPA (enable large physical addressing) is set. On an XPA kernel though the size of PTEs is fixed at 8 bytes regardless of whether XPA could actually be enabled. Fix the initialisation of this field based on sizeof(pte_t) instead. Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan Cc: Steven J. Hill Cc: Paul Burton Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13113/ Signed-off-by: Paul Burton Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 7153e1fb0cd4..baad605db878 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2424,9 +2424,7 @@ static void config_htw_params(void) if (CONFIG_PGTABLE_LEVELS >= 3) pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT; - /* If XPA has been enabled, PTEs are 64-bit in size. */ - if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA)) - pwsize |= 1; + pwsize |= ilog2(sizeof(pte_t)/4) << MIPS_PWSIZE_PTEW_SHIFT; write_c0_pwsize(pwsize); -- cgit v1.2.3-59-g8ed1b From 253f0d4a5fdcba9367b83df7fb504407efc20ec2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:01 +0100 Subject: MIPS: Remove redundant asm/pgtable-bits.h inclusions asm/pgtable-bits.h is included in 2 assembly files and thus has to ifdef around C code, however nothing defined by the header is used in either of the assembly files that include it. Remove the redundant inclusions such that asm/pgtable-bits.h doesn't need to #ifdef around C code, for cleanliness and in preparation for later patches which will add more C. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Maciej W. Rozycki Cc: Jonas Gorski Cc: Alex Smith Cc: Kirill A. Shutemov Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13114/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 2 -- arch/mips/kernel/head.S | 1 - arch/mips/kernel/r4k_switch.S | 1 - 3 files changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 97b313882678..2f4031209d54 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -191,7 +191,6 @@ */ -#ifndef __ASSEMBLY__ /* * pte_to_entrylo converts a page table entry (PTE) into a Mips * entrylo0/1 value. @@ -218,7 +217,6 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) return pte_val >> _PAGE_GLOBAL_SHIFT; } -#endif /* * Cache attributes diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 7dc043349d66..56e8fede3fd8 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 92cd0516ecf5..2f0a3b223c97 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 694977006a7ba71e33e1f5df4f66ffd5ae19ec84 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:02 +0100 Subject: MIPS: Use enums to make asm/pgtable-bits.h readable asm/pgtable-bits.h has grown to become an unreadable mess of #ifdef directives defining bits conditionally upon other bits all at the preprocessing stage, for no good reason. Instead of having quite so many #ifdef's, simply use enums to provide sequential numbering for bit shifts, without having to keep track manually of what the last bit defined was. Masks are defined separately, after the shifts, which allows for most of their definitions to be reused for all systems rather than duplicated. This patch is not intended to make any behavioural change to the code - all bits should be used in the same way they were before this patch. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Maciej W. Rozycki Cc: Alex Smith Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13115/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 189 +++++++++++++++-------------------- 1 file changed, 81 insertions(+), 108 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 2f4031209d54..c81fc1703c8a 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -35,36 +35,25 @@ #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) /* - * The following bits are implemented by the TLB hardware + * Page table bit offsets used for 64 bit physical addressing on MIPS32, + * for example with Alchemy, Netlogic XLP/XLR or XPA. */ -#define _PAGE_NO_EXEC_SHIFT 0 -#define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -#define _PAGE_NO_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) -#define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) -#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) -#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) -#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_MASK (7 << _CACHE_SHIFT) - -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT (24) -#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) -#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) -#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) - -#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) +enum pgtable_bits { + /* Used by TLB hardware (placed in EntryLo*) */ + _PAGE_NO_EXEC_SHIFT, + _PAGE_NO_READ_SHIFT, + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, + + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT = 24, + _PAGE_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +}; /* * Bits for extended EntryLo0/EntryLo1 registers @@ -73,101 +62,85 @@ #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT (0) -#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) -#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) -#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) +/* Page table bits used for r3k systems */ +enum pgtable_bits { + /* Used only by software (writes to EntryLo ignored) */ + _PAGE_PRESENT_SHIFT, + _PAGE_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, + + /* Used by TLB hardware (placed in EntryLo) */ + _PAGE_GLOBAL_SHIFT = 8, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_UNCACHED_SHIFT, +}; -/* - * The following bits are implemented by the TLB hardware - */ -#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 4) -#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) -#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) -#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_UNCACHED_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT) -#define _CACHE_MASK _CACHE_UNCACHED +#else -#define _PFN_SHIFT PAGE_SHIFT +/* Page table bits used for r4k systems */ +enum pgtable_bits { + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT, +#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) + _PAGE_READ_SHIFT, +#endif + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +#if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) + _PAGE_HUGE_SHIFT, +#endif -#else -/* - * Below are the "Normal" R4K cases - */ + /* Used by TLB hardware (placed in EntryLo*) */ +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) + _PAGE_NO_EXEC_SHIFT, + _PAGE_NO_READ_SHIFT, + _PAGE_READ_SHIFT = _PAGE_NO_READ_SHIFT, +#endif + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, +}; -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT 0 +#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ + +/* Used only by software */ #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -/* R2 or later cores check for RI/XI support to determine _PAGE_READ */ #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -#define _PAGE_WRITE_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +# define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) #else -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +# define _PAGE_READ (1 << _PAGE_READ_SHIFT) #endif -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) +#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) - #if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) -/* Huge TLB page */ -#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT + 1) -#define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT) -#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */ - -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -/* XI - page cannot be executed */ -#ifdef _PAGE_HUGE_SHIFT -#define _PAGE_NO_EXEC_SHIFT (_PAGE_HUGE_SHIFT + 1) -#else -#define _PAGE_NO_EXEC_SHIFT (_PAGE_MODIFIED_SHIFT + 1) +# define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT) #endif -#define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) - -/* RI - page cannot be read */ -#define _PAGE_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) -#define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) -#define _PAGE_NO_READ_SHIFT _PAGE_READ_SHIFT -#define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0) -#endif /* defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) */ - -#if defined(_PAGE_NO_READ_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) -#elif defined(_PAGE_HUGE_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_HUGE_SHIFT + 1) -#else -#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 1) + +/* Used by TLB hardware (placed in EntryLo*) */ +#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) +# define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) +# define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) +#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +# define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) +# define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_NO_READ_SHIFT) : 0) #endif #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) - -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_MASK (7 << _CACHE_SHIFT) - -#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) - -#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +# define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT) +# define _CACHE_MASK _CACHE_UNCACHED +# define _PFN_SHIFT PAGE_SHIFT +#else +# define _CACHE_MASK (7 << _CACHE_SHIFT) +# define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) +#endif #ifndef _PAGE_NO_EXEC #define _PAGE_NO_EXEC 0 -- cgit v1.2.3-59-g8ed1b From 780602d740fc0b723ea3a05bd7f35d2d7f31aa68 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:03 +0100 Subject: MIPS: mm: Standardise on _PAGE_NO_READ, drop _PAGE_READ Ever since support for RI/XI was implemented by commit 6dd9344cfc41 ("MIPS: Implement Read Inhibit/eXecute Inhibit") we've had a mixture of _PAGE_READ & _PAGE_NO_READ bits. Rather than keep both around, switch away from using _PAGE_READ to determine page presence & instead invert the use to _PAGE_NO_READ. Wherever we formerly had no definition for _PAGE_NO_READ, change what was _PAGE_READ to _PAGE_NO_READ. The end result is that we consistently use _PAGE_NO_READ to determine whether a page is readable, regardless of whether RI/XI is implemented. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: David Daney Cc: Huacai Chen Cc: Maciej W. Rozycki Cc: Paul Gortmaker Cc: Aneesh Kumar K.V Cc: Andrew Morton Cc: Alex Smith Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13116/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 19 ++++--------------- arch/mips/include/asm/pgtable.h | 23 +++++++---------------- arch/mips/mm/tlbex.c | 13 ++++--------- 3 files changed, 15 insertions(+), 40 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index c81fc1703c8a..5bc663d330d2 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -49,7 +49,6 @@ enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT = 24, - _PAGE_READ_SHIFT, _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, _PAGE_MODIFIED_SHIFT, @@ -66,7 +65,7 @@ enum pgtable_bits { enum pgtable_bits { /* Used only by software (writes to EntryLo ignored) */ _PAGE_PRESENT_SHIFT, - _PAGE_READ_SHIFT, + _PAGE_NO_READ_SHIFT, _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, _PAGE_MODIFIED_SHIFT, @@ -85,7 +84,7 @@ enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT, #if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) - _PAGE_READ_SHIFT, + _PAGE_NO_READ_SHIFT, #endif _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, @@ -98,7 +97,6 @@ enum pgtable_bits { #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) _PAGE_NO_EXEC_SHIFT, _PAGE_NO_READ_SHIFT, - _PAGE_READ_SHIFT = _PAGE_NO_READ_SHIFT, #endif _PAGE_GLOBAL_SHIFT, _PAGE_VALID_SHIFT, @@ -110,11 +108,6 @@ enum pgtable_bits { /* Used only by software */ #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -# define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) -#else -# define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#endif #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) @@ -125,11 +118,10 @@ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ #if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -# define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) -# define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_NO_READ_SHIFT) : 0) #endif +#define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) @@ -145,9 +137,6 @@ enum pgtable_bits { #ifndef _PAGE_NO_EXEC #define _PAGE_NO_EXEC 0 #endif -#ifndef _PAGE_NO_READ -#define _PAGE_NO_READ 0 -#endif #define _PAGE_SILENT_READ _PAGE_VALID #define _PAGE_SILENT_WRITE _PAGE_DIRTY @@ -245,7 +234,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) #endif -#define __READABLE (_PAGE_SILENT_READ | _PAGE_READ | _PAGE_ACCESSED) +#define __READABLE (_PAGE_SILENT_READ | _PAGE_ACCESSED) #define __WRITEABLE (_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (_PAGE_ACCESSED | _PAGE_MODIFIED | \ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 7f422500b65d..f6de4f49b1b2 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -23,18 +23,19 @@ struct mm_struct; struct vm_area_struct; -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | \ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \ + _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \ _page_cachable_default) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_NO_EXEC | \ +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | \ _page_cachable_default) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | \ _page_cachable_default) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _page_cachable_default) #define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \ _page_cachable_default) #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED) @@ -338,7 +339,7 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte.pte_low |= _PAGE_ACCESSED; - if (pte.pte_low & _PAGE_READ) + if (!(pte.pte_low & _PAGE_NO_READ)) pte.pte_high |= _PAGE_SILENT_READ; return pte; } @@ -384,13 +385,8 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pte_val(pte) & _PAGE_NO_READ)) pte_val(pte) |= _PAGE_SILENT_READ; - else -#endif - if (pte_val(pte) & _PAGE_READ) - pte_val(pte) |= _PAGE_SILENT_READ; return pte; } @@ -570,13 +566,8 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) { pmd_val(pmd) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pmd_val(pmd) & _PAGE_NO_READ)) pmd_val(pmd) |= _PAGE_SILENT_READ; - else -#endif - if (pmd_val(pmd) & _PAGE_READ) - pmd_val(pmd) |= _PAGE_SILENT_READ; return pmd; } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index baad605db878..67966f30c522 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -234,20 +234,16 @@ static void output_pgtable_bits_defines(void) pr_debug("\n"); pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT); - pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT); + pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT); pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT); pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT); #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT); #endif -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) - if (cpu_has_rixi) { #ifdef _PAGE_NO_EXEC_SHIFT + if (cpu_has_rixi) pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT); - pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); -#endif - } #endif pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT); pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT); @@ -1728,9 +1724,8 @@ build_pte_present(u32 **p, struct uasm_reloc **r, cur = t; } uasm_i_andi(p, t, cur, - (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); - uasm_i_xori(p, t, t, - (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); + (_PAGE_PRESENT | _PAGE_NO_READ) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, _PAGE_PRESENT >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ -- cgit v1.2.3-59-g8ed1b From 745f35587846249b392aa548b4c5f54cd69ed688 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:04 +0100 Subject: MIPS: mm: Unify pte_page definition The same definition for pte_page is duplicated for the MIPS32 PHYS_ADDR_T_64BIT case & the generic case. Unify them by moving a single definition outside of preprocessor conditionals. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13117/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 832e2167d00f..181bd8e7db7d 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -104,7 +104,7 @@ static inline void pmd_clear(pmd_t *pmdp) } #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -#define pte_page(x) pfn_to_page(pte_pfn(x)) + #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) @@ -120,8 +120,6 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #else -#define pte_page(x) pfn_to_page(pte_pfn(x)) - #ifdef CONFIG_CPU_VR41XX #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) @@ -131,6 +129,8 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #endif #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */ +#define pte_page(x) pfn_to_page(pte_pfn(x)) + #define __pgd_offset(address) pgd_index(address) #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) #define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -- cgit v1.2.3-59-g8ed1b From 7b2cb64f91f25a7293b10054e20d1c0734ffab6f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:05 +0100 Subject: MIPS: mm: Fix MIPS32 36b physical addressing (alchemy, netlogic) There are 2 distinct cases in which a kernel for a MIPS32 CPU (CONFIG_CPU_MIPS32=y) may use 64 bit physical addresses (CONFIG_PHYS_ADDR_T_64BIT=y): - 36 bit physical addressing as used by RMI Alchemy & Netlogic XLP/XLR CPUs. - MIPS32r5 eXtended Physical Addressing (XPA). These 2 cases are distinct in that they require different behaviour from the kernel - the EntryLo registers have different formats. Until Linux v4.1 we only supported the first case, with code conditional upon the 2 aforementioned Kconfig variables being set. Commit c5b367835cfc ("MIPS: Add support for XPA.") added support for the second case, but did so by modifying the code that existed for the first case rather than treating the 2 cases as distinct. Since the EntryLo registers have different formats this breaks the 36 bit Alchemy/XLP/XLR case. Fix this by splitting the 2 cases, with XPA cases now being conditional upon CONFIG_XPA and the non-XPA case matching the code as it existed prior to commit c5b367835cfc ("MIPS: Add support for XPA."). Signed-off-by: Paul Burton Reported-by: Manuel Lauss Tested-by: Manuel Lauss Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Cc: James Hogan Cc: David Daney Cc: Huacai Chen Cc: Maciej W. Rozycki Cc: Paul Gortmaker Cc: Aneesh Kumar K.V Cc: Peter Zijlstra (Intel) Cc: David Hildenbrand Cc: Andrew Morton Cc: Ingo Molnar Cc: Alex Smith Cc: Kirill A. Shutemov Cc: stable@vger.kernel.org # v4.1+ Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13119/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-32.h | 27 +++++++++++++++-- arch/mips/include/asm/pgtable-bits.h | 29 +++++++++++++++--- arch/mips/include/asm/pgtable.h | 57 +++++++++++++++++++++++++++++++----- arch/mips/mm/init.c | 4 ++- arch/mips/mm/tlbex.c | 35 ++++++++++++++-------- 5 files changed, 125 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 181bd8e7db7d..d21f3da7bdb6 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -103,7 +103,7 @@ static inline void pmd_clear(pmd_t *pmdp) pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); } -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t @@ -118,6 +118,20 @@ pfn_pte(unsigned long pfn, pgprot_t prot) return pte; } +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) + +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) +{ + pte_t pte; + + pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f); + pte.pte_low = pgprot_val(prot); + + return pte; +} + #else #ifdef CONFIG_CPU_VR41XX @@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #else -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) /* Swap entries must have VALID and GLOBAL bits cleared. */ #define __swp_type(x) (((x).val >> 4) & 0x1f) @@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +/* Swap entries must have VALID and GLOBAL bits cleared. */ +#define __swp_type(x) (((x).val >> 2) & 0x1f) +#define __swp_offset(x) ((x).val >> 7) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) +#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) + #else /* * Constraints: diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 5bc663d330d2..58e8bf815404 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -32,11 +32,11 @@ * unpredictable things. The code (when it is written) to deal with * this problem will be in the update_mmu_cache() code for the r4k. */ -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) /* - * Page table bit offsets used for 64 bit physical addressing on MIPS32, - * for example with Alchemy, Netlogic XLP/XLR or XPA. + * Page table bit offsets used for 64 bit physical addressing on + * MIPS32r5 with XPA. */ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ @@ -59,6 +59,27 @@ enum pgtable_bits { */ #define _PFNX_MASK 0xffffff +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +/* + * Page table bit offsets used for 36 bit physical addressing on MIPS32, + * for example with Alchemy or Netlogic XLP/XLR. + */ +enum pgtable_bits { + /* Used by TLB hardware (placed in EntryLo*) */ + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, + + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT = _CACHE_SHIFT + 3, + _PAGE_NO_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +}; + #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) /* Page table bits used for r3k systems */ @@ -116,7 +137,7 @@ enum pgtable_bits { #endif /* Used by TLB hardware (placed in EntryLo*) */ -#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) +#if defined(CONFIG_XPA) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index f6de4f49b1b2..e07a105cafc2 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -133,7 +133,12 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) +#ifdef CONFIG_XPA +# define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) +#else +# define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) +#endif + #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) #define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) @@ -143,14 +148,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) smp_wmb(); ptep->pte_low = pte.pte_low; +#ifdef CONFIG_XPA if (pte.pte_high & _PAGE_GLOBAL) { +#else + if (pte.pte_low & _PAGE_GLOBAL) { +#endif pte_t *buddy = ptep_buddy(ptep); /* * Make sure the buddy is global too (if it's !none, * it better already be global) */ - if (pte_none(*buddy)) + if (pte_none(*buddy)) { + if (!config_enabled(CONFIG_XPA)) + buddy->pte_low |= _PAGE_GLOBAL; buddy->pte_high |= _PAGE_GLOBAL; + } } } @@ -160,8 +172,13 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt htw_stop(); /* Preserve global status for the pair */ - if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) - null.pte_high = _PAGE_GLOBAL; + if (config_enabled(CONFIG_XPA)) { + if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) + null.pte_high = _PAGE_GLOBAL; + } else { + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) + null.pte_low = null.pte_high = _PAGE_GLOBAL; + } set_pte_at(mm, addr, ptep, null); htw_start(); @@ -302,6 +319,8 @@ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } static inline pte_t pte_wrprotect(pte_t pte) { pte.pte_low &= ~_PAGE_WRITE; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_WRITE; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } @@ -309,6 +328,8 @@ static inline pte_t pte_wrprotect(pte_t pte) static inline pte_t pte_mkclean(pte_t pte) { pte.pte_low &= ~_PAGE_MODIFIED; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_WRITE; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } @@ -316,6 +337,8 @@ static inline pte_t pte_mkclean(pte_t pte) static inline pte_t pte_mkold(pte_t pte) { pte.pte_low &= ~_PAGE_ACCESSED; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_READ; pte.pte_high &= ~_PAGE_SILENT_READ; return pte; } @@ -323,24 +346,33 @@ static inline pte_t pte_mkold(pte_t pte) static inline pte_t pte_mkwrite(pte_t pte) { pte.pte_low |= _PAGE_WRITE; - if (pte.pte_low & _PAGE_MODIFIED) + if (pte.pte_low & _PAGE_MODIFIED) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_WRITE; pte.pte_high |= _PAGE_SILENT_WRITE; + } return pte; } static inline pte_t pte_mkdirty(pte_t pte) { pte.pte_low |= _PAGE_MODIFIED; - if (pte.pte_low & _PAGE_WRITE) + if (pte.pte_low & _PAGE_WRITE) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_WRITE; pte.pte_high |= _PAGE_SILENT_WRITE; + } return pte; } static inline pte_t pte_mkyoung(pte_t pte) { pte.pte_low |= _PAGE_ACCESSED; - if (!(pte.pte_low & _PAGE_NO_READ)) + if (!(pte.pte_low & _PAGE_NO_READ)) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_READ; pte.pte_high |= _PAGE_SILENT_READ; + } return pte; } #else @@ -438,7 +470,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) */ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte.pte_low &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); @@ -447,6 +479,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK; return pte; } +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte.pte_low &= _PAGE_CHG_MASK; + pte.pte_high &= (_PFN_MASK | _CACHE_MASK); + pte.pte_low |= pgprot_val(newprot); + pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); + return pte; +} #else static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 6c6a843b0d17..134c988bc61f 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) idx += in_interrupt() ? FIX_N_COLOURS : 0; vaddr = __fix_to_virt(FIX_CMAP_END - idx); pte = mk_pte(page, prot); -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) entrylo = pte_to_entrylo(pte.pte_high); +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + entrylo = pte.pte_high; #else entrylo = pte_to_entrylo(pte_val(pte)); #endif diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 67966f30c522..db4adf9cc65c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1011,25 +1011,21 @@ static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { - /* - * 64bit address support (36bit on a 32bit CPU) in a 32bit - * Kernel is a special case. Only a few CPUs use it. - */ - if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { + if (config_enabled(CONFIG_XPA)) { int pte_off_even = sizeof(pte_t) / 2; int pte_off_odd = pte_off_even + sizeof(pte_t); -#ifdef CONFIG_XPA const int scratch = 1; /* Our extra working register */ uasm_i_addu(p, scratch, 0, ptep); -#endif + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); + + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ + UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, ptep, C0_ENTRYLO1); -#ifdef CONFIG_XPA + uasm_i_lw(p, tmp, 0, scratch); uasm_i_lw(p, ptep, sizeof(pte_t), scratch); uasm_i_lui(p, scratch, 0xff); @@ -1038,7 +1034,22 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) uasm_i_and(p, ptep, scratch, ptep); uasm_i_mthc0(p, tmp, C0_ENTRYLO0); uasm_i_mthc0(p, ptep, C0_ENTRYLO1); -#endif + return; + } + + /* + * 64bit address support (36bit on a 32bit CPU) in a 32bit + * Kernel is a special case. Only a few CPUs use it. + */ + if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { + int pte_off_even = sizeof(pte_t) / 2; + int pte_off_odd = pte_off_even + sizeof(pte_t); + + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); + + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ + UASM_i_MTC0(p, ptep, C0_ENTRYLO1); return; } @@ -1637,7 +1648,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, #ifdef CONFIG_PHYS_ADDR_T_64BIT unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); - if (!cpu_has_64bits) { + if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { const int scratch = 1; /* Our extra working register */ uasm_i_lui(p, scratch, (mode >> 16)); -- cgit v1.2.3-59-g8ed1b From f383219674b72f390911c60e1d8ae95e32622398 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 19 Apr 2016 09:25:06 +0100 Subject: MIPS: mm: Don't clobber $1 on XPA TLB refill For XPA kernels build_update_entries() uses $1 (at) as a scratch register, but doesn't arrange for it to be preserved, so it will always be clobbered by the TLB refill exception. Although this register normally has a very short lifetime that doesn't cross memory accesses, TLB refills due to instruction fetches (either on a page boundary or after preemption) could clobber live data, and its easy to reproduce the clobber with a little bit of assembler code. Note that the use of a hardware page table walker will partly mask the problem, as the TLB refill handler will not always be invoked. This is fixed by avoiding the use of the extra scratch register. The pte_high parts (going into the lower half of the EntryLo registers) are loaded and manipulated separately so as to keep the PTE pointer around for the other halves (instead of storing in the scratch register), and the pte_low parts (going into the high half of the EntryLo registers) are masked with 0x00ffffff using an ext instruction (instead of loading 0x00ffffff into the scratch register and AND'ing). [paul.burton@imgtec.com: - Rebase atop other TLB work. - Use ext instead of an sll, srl sequence. - Use cpu_has_xpa instead of #ifdefs. - Modify commit subject to include "mm".] Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan Signed-off-by: Paul Burton Cc: Paul Gortmaker Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13120/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index db4adf9cc65c..81d42c33f882 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1014,26 +1014,22 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) if (config_enabled(CONFIG_XPA)) { int pte_off_even = sizeof(pte_t) / 2; int pte_off_odd = pte_off_even + sizeof(pte_t); - const int scratch = 1; /* Our extra working register */ - - uasm_i_addu(p, scratch, 0, ptep); uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); - UASM_i_MTC0(p, ptep, C0_ENTRYLO1); - - uasm_i_lw(p, tmp, 0, scratch); - uasm_i_lw(p, ptep, sizeof(pte_t), scratch); - uasm_i_lui(p, scratch, 0xff); - uasm_i_ori(p, scratch, scratch, 0xffff); - uasm_i_and(p, tmp, scratch, tmp); - uasm_i_and(p, ptep, scratch, ptep); + uasm_i_lw(p, tmp, 0, ptep); + uasm_i_ext(p, tmp, tmp, 0, 24); uasm_i_mthc0(p, tmp, C0_ENTRYLO0); - uasm_i_mthc0(p, ptep, C0_ENTRYLO1); + + uasm_i_lw(p, tmp, pte_off_odd, ptep); /* odd pte */ + UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); + UASM_i_MTC0(p, tmp, C0_ENTRYLO1); + + uasm_i_lw(p, tmp, sizeof(pte_t), ptep); + uasm_i_ext(p, tmp, tmp, 0, 24); + uasm_i_mthc0(p, tmp, C0_ENTRYLO1); return; } -- cgit v1.2.3-59-g8ed1b From bbeeffec6f14a04454906032e9322538535030dc Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:07 +0100 Subject: MIPS: mm: Pass scratch register through to iPTE_SW Rather than hardcode a scratch register for the XPA case in iPTE_SW, pass one through from the work registers allocated by the caller. This allows for the XPA path to function correctly regardless of the work registers in use. Without doing this there are cases (where KScratch registers are unavailable) in which iPTE_SW will incorrectly clobber $1 despite it already being in use for the PTE or PTE pointer. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13121/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 81d42c33f882..2e9b43637743 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1639,14 +1639,12 @@ iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) static void iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, - unsigned int mode) + unsigned int mode, unsigned int scratch) { #ifdef CONFIG_PHYS_ADDR_T_64BIT unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { - const int scratch = 1; /* Our extra working register */ - uasm_i_lui(p, scratch, (mode >> 16)); uasm_i_or(p, pte, pte, scratch); } else @@ -1743,11 +1741,11 @@ build_pte_present(u32 **p, struct uasm_reloc **r, /* Make PTE valid, store result in PTR. */ static void build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, - unsigned int ptr) + unsigned int ptr, unsigned int scratch) { unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED; - iPTE_SW(p, r, pte, ptr, mode); + iPTE_SW(p, r, pte, ptr, mode, scratch); } /* @@ -1783,12 +1781,12 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, */ static void build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, - unsigned int ptr) + unsigned int ptr, unsigned int scratch) { unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); - iPTE_SW(p, r, pte, ptr, mode); + iPTE_SW(p, r, pte, ptr, mode, scratch); } /* @@ -1893,7 +1891,7 @@ static void build_r3000_tlb_load_handler(void) build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl); uasm_i_nop(&p); /* load delay */ - build_make_valid(&p, &r, K0, K1); + build_make_valid(&p, &r, K0, K1, -1); build_r3000_tlb_reload_write(&p, &l, &r, K0, K1); uasm_l_nopage_tlbl(&l, p); @@ -1924,7 +1922,7 @@ static void build_r3000_tlb_store_handler(void) build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs); uasm_i_nop(&p); /* load delay */ - build_make_write(&p, &r, K0, K1); + build_make_write(&p, &r, K0, K1, -1); build_r3000_tlb_reload_write(&p, &l, &r, K0, K1); uasm_l_nopage_tlbs(&l, p); @@ -1955,7 +1953,7 @@ static void build_r3000_tlb_modify_handler(void) build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_modifiable(&p, &r, K0, K1, -1, label_nopage_tlbm); uasm_i_nop(&p); /* load delay */ - build_make_write(&p, &r, K0, K1); + build_make_write(&p, &r, K0, K1, -1); build_r3000_pte_reload_tlbwi(&p, K0, K1); uasm_l_nopage_tlbm(&l, p); @@ -2123,7 +2121,7 @@ static void build_r4000_tlb_load_handler(void) } uasm_l_tlbl_goaround1(&l, p); } - build_make_valid(&p, &r, wr.r1, wr.r2); + build_make_valid(&p, &r, wr.r1, wr.r2, wr.r3); build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2); #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT @@ -2237,7 +2235,7 @@ static void build_r4000_tlb_store_handler(void) build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); - build_make_write(&p, &r, wr.r1, wr.r2); + build_make_write(&p, &r, wr.r1, wr.r2, wr.r3); build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2); #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT @@ -2293,7 +2291,7 @@ static void build_r4000_tlb_modify_handler(void) if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); /* Present and writable bits set, set accessed and dirty bits. */ - build_make_write(&p, &r, wr.r1, wr.r2); + build_make_write(&p, &r, wr.r1, wr.r2, wr.r3); build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2); #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT -- cgit v1.2.3-59-g8ed1b From b4ebbb876dca9327cc964138f5558ca3c6832392 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:08 +0100 Subject: MIPS: mm: Be more explicit about PTE mode bit handling The XPA case in iPTE_SW or's in software mode bits to the pte_low value (which is what actually ends up in the high 32 bits of EntryLo...). It does this presuming that only bits in the upper 16 bits of the 32 bit pte_low value will be set. Make this assumption explicit with a BUG_ON. A similar assumption is made for the hardware mode bits, which are or'd in with a single ori instruction. Make that assumption explicit with a BUG_ON too. Signed-off-by: Paul Burton Cc: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13122/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 2e9b43637743..6f20b42be979 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1641,15 +1641,17 @@ static void iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, unsigned int mode, unsigned int scratch) { -#ifdef CONFIG_PHYS_ADDR_T_64BIT unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); + unsigned int swmode = mode & ~hwmode; if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { - uasm_i_lui(p, scratch, (mode >> 16)); + uasm_i_lui(p, scratch, swmode >> 16); uasm_i_or(p, pte, pte, scratch); - } else -#endif - uasm_i_ori(p, pte, pte, mode); + BUG_ON(swmode & 0xffff); + } else { + uasm_i_ori(p, pte, pte, mode); + } + #ifdef CONFIG_SMP # ifdef CONFIG_PHYS_ADDR_T_64BIT if (cpu_has_64bits) @@ -1668,6 +1670,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, /* no uasm_i_nop needed */ uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr); uasm_i_ori(p, pte, pte, hwmode); + BUG_ON(hwmode & ~0xffff); uasm_i_sc(p, pte, sizeof(pte_t) / 2, ptr); uasm_il_beqz(p, r, pte, label_smp_pgtable_change); /* no uasm_i_nop needed */ @@ -1689,6 +1692,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, if (!cpu_has_64bits) { uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr); uasm_i_ori(p, pte, pte, hwmode); + BUG_ON(hwmode & ~0xffff); uasm_i_sw(p, pte, sizeof(pte_t) / 2, ptr); uasm_i_lw(p, pte, 0, ptr); } -- cgit v1.2.3-59-g8ed1b From 2caa89b49b21737b2b7b6fce37cb323535188b06 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:09 +0100 Subject: MIPS: mm: Simplify build_update_entries We can simplify build_update_entries by unifying the code for the 36 bit physical addressing with MIPS32 case with the general case, by using pte_off_ variables in all cases & handling the trivial _PAGE_GLOBAL_SHIFT == 0 case in build_convert_pte_to_entrylo. This leaves XPA as the only special case. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13123/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 6f20b42be979..588bde3bdbe7 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -631,6 +631,11 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l, static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, unsigned int reg) { + if (_PAGE_GLOBAL_SHIFT == 0) { + /* pte_t is already in EntryLo format */ + return; + } + if (cpu_has_rixi && _PAGE_NO_EXEC) { if (fill_includes_sw_bits) { UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); @@ -1011,10 +1016,16 @@ static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { - if (config_enabled(CONFIG_XPA)) { - int pte_off_even = sizeof(pte_t) / 2; - int pte_off_odd = pte_off_even + sizeof(pte_t); + int pte_off_even = 0; + int pte_off_odd = sizeof(pte_t); +#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_PHYS_ADDR_T_64BIT) + /* The low 32 bits of EntryLo is stored in pte_high */ + pte_off_even += offsetof(pte_t, pte_high); + pte_off_odd += offsetof(pte_t, pte_high); +#endif + + if (config_enabled(CONFIG_XPA)) { uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); @@ -1033,24 +1044,8 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) return; } - /* - * 64bit address support (36bit on a 32bit CPU) in a 32bit - * Kernel is a special case. Only a few CPUs use it. - */ - if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { - int pte_off_even = sizeof(pte_t) / 2; - int pte_off_odd = pte_off_even + sizeof(pte_t); - - uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); - - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ - UASM_i_MTC0(p, ptep, C0_ENTRYLO1); - return; - } - - UASM_i_LW(p, tmp, 0, ptep); /* get even pte */ - UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ + UASM_i_LW(p, tmp, pte_off_even, ptep); /* get even pte */ + UASM_i_LW(p, ptep, pte_off_odd, ptep); /* get odd pte */ if (r45k_bvahwbug()) build_tlb_probe_entry(p); build_convert_pte_to_entrylo(p, tmp); -- cgit v1.2.3-59-g8ed1b From 4b6f99d307ed6c7a28b952bfb7b66fb26a6a4cf0 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 19 Apr 2016 09:25:10 +0100 Subject: MIPS: mm: Don't do MTHC0 if XPA not present Performing an MTHC0 instruction without XPA being present will trigger a reserved instruction exception, therefore conditionalise the use of this instruction when building TLB handlers (build_update_entries()), and in __update_tlb(). This allows an XPA kernel to run on non XPA hardware without that instruction implemented, just like it can run on XPA capable hardware without XPA in use (with the noxpa kernel argument) or with XPA not configured in hardware. [paul.burton@imgtec.com: - Rebase atop other TLB work. - Add "mm" to subject. - Handle the __kmap_pgprot case.] Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan Signed-off-by: Paul Burton Cc: Paul Gortmaker Cc: David Hildenbrand Cc: Andrew Morton Cc: Jerome Marchand Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13124/ Signed-off-by: Ralf Baechle --- arch/mips/mm/init.c | 8 +++++--- arch/mips/mm/tlb-r4k.c | 6 ++++-- arch/mips/mm/tlbex.c | 16 ++++++++++------ 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 134c988bc61f..9b58eb5fd0d5 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -112,9 +112,11 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) write_c0_entrylo0(entrylo); write_c0_entrylo1(entrylo); #ifdef CONFIG_XPA - entrylo = (pte.pte_low & _PFNX_MASK); - writex_c0_entrylo0(entrylo); - writex_c0_entrylo1(entrylo); + if (cpu_has_xpa) { + entrylo = (pte.pte_low & _PFNX_MASK); + writex_c0_entrylo0(entrylo); + writex_c0_entrylo1(entrylo); + } #endif tlbidx = read_c0_wired(); write_c0_wired(tlbidx + 1); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 61f1f1ba4a17..5a5c7fec645e 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -339,10 +339,12 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) #ifdef CONFIG_XPA write_c0_entrylo0(pte_to_entrylo(ptep->pte_high)); - writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK); + if (cpu_has_xpa) + writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK); ptep++; write_c0_entrylo1(pte_to_entrylo(ptep->pte_high)); - writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK); + if (cpu_has_xpa) + writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK); #else write_c0_entrylo0(ptep->pte_high); ptep++; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 588bde3bdbe7..0efa6211cc40 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1030,17 +1030,21 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); - uasm_i_lw(p, tmp, 0, ptep); - uasm_i_ext(p, tmp, tmp, 0, 24); - uasm_i_mthc0(p, tmp, C0_ENTRYLO0); + if (cpu_has_xpa && !mips_xpa_disabled) { + uasm_i_lw(p, tmp, 0, ptep); + uasm_i_ext(p, tmp, tmp, 0, 24); + uasm_i_mthc0(p, tmp, C0_ENTRYLO0); + } uasm_i_lw(p, tmp, pte_off_odd, ptep); /* odd pte */ UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO1); - uasm_i_lw(p, tmp, sizeof(pte_t), ptep); - uasm_i_ext(p, tmp, tmp, 0, 24); - uasm_i_mthc0(p, tmp, C0_ENTRYLO1); + if (cpu_has_xpa && !mips_xpa_disabled) { + uasm_i_lw(p, tmp, sizeof(pte_t), ptep); + uasm_i_ext(p, tmp, tmp, 0, 24); + uasm_i_mthc0(p, tmp, C0_ENTRYLO1); + } return; } -- cgit v1.2.3-59-g8ed1b From e56c7e18818dd721179f9ca95c77dd941a360384 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:11 +0100 Subject: MIPS: mm: Panic if an XPA kernel is run without RIXI XPA kernels hardcode for the presence of RIXI - the PTE format & its handling presume RI & XI bits. Make this dependence explicit by panicing if we run on a system that violates it. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13125/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 0efa6211cc40..274da90adf0d 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2508,6 +2508,9 @@ void build_tlb_refill_handler(void) */ static int run_once = 0; + if (config_enabled(CONFIG_XPA) && !cpu_has_rixi) + panic("Kernels supporting XPA currently require CPUs with RIXI"); + output_pgtable_bits_defines(); check_pabits(); -- cgit v1.2.3-59-g8ed1b From 8256b17ecb028949d80c982d0f28ad46fe4e73d8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:51 -0800 Subject: MIPS: Allow RIXI to be used on non-R2 or R6 cores Some processors, like Broadcom's BMIPS4380 and BMIPS5000 support RIXI and the "rotr" instruction, which can be used to get a slightly more efficient page table layout. Introduce a CONFIG_CPU_HAS_RIXI such that those cores can benefit from this feature. Perform the conditional check updates where relevant. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12505/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 5 +++++ arch/mips/include/asm/pgtable-bits.h | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d10ed57ad418..5562ee535db8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1996,11 +1996,13 @@ config CPU_MIPSR1 config CPU_MIPSR2 bool default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON + select CPU_HAS_RIXI select MIPS_SPRAM config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 + select CPU_HAS_RIXI select HAVE_ARCH_BITREVERSE select MIPS_ASID_BITS_VARIABLE select MIPS_SPRAM @@ -2421,6 +2423,9 @@ config CPU_HAS_WB config XKS01 bool +config CPU_HAS_RIXI + bool + # # Vectored interrupt mode is an R2 feature # diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 58e8bf815404..f88a48cd68b2 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -104,7 +104,7 @@ enum pgtable_bits { enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT, -#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) +#if !defined(CONFIG_CPU_HAS_RIXI) _PAGE_NO_READ_SHIFT, #endif _PAGE_WRITE_SHIFT, @@ -115,7 +115,7 @@ enum pgtable_bits { #endif /* Used by TLB hardware (placed in EntryLo*) */ -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_HAS_RIXI) _PAGE_NO_EXEC_SHIFT, _PAGE_NO_READ_SHIFT, #endif @@ -139,7 +139,7 @@ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ #if defined(CONFIG_XPA) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#elif defined(CONFIG_CPU_HAS_RIXI) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) #endif #define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) @@ -180,7 +180,7 @@ enum pgtable_bits { */ static inline uint64_t pte_to_entrylo(unsigned long pte_val) { -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#ifdef CONFIG_CPU_HAS_RIXI if (cpu_has_rixi) { int sa; #ifdef CONFIG_32BIT -- cgit v1.2.3-59-g8ed1b From 2e274768e4dd9565a31cd1979ed6d534cd4e656f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:52 -0800 Subject: MIPS: Move RIXI exception enabling after vendor-specific cpu_probe Some processors may not have the RIXI bit advertised in the Config3 register, not being a MIPS32R2 or R6 core, yet, they might be supporting it through a different way, which is overriden during vendor-specific cpu_probe(). Move the RIXI exceptions enabling after the vendor-specific cpu_probe() function has had a change to run and override the current CPU's options with MIPS_CPU_RIXI. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12506/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8eda42a9ca59..4bcbf002a8f7 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -862,15 +862,6 @@ static void decode_configs(struct cpuinfo_mips *c) mips_probe_watch_registers(c); - if (cpu_has_rixi) { - /* Enable the RIXI exceptions */ - set_c0_pagegrain(PG_IEC); - back_to_back_c0_hazard(); - /* Verify the IEC bit is set */ - if (read_c0_pagegrain() & PG_IEC) - c->options |= MIPS_CPU_RIXIEX; - } - #ifndef CONFIG_MIPS_CPS if (cpu_has_mips_r2_r6) { c->core = get_ebase_cpunum(); @@ -1733,6 +1724,15 @@ void cpu_probe(void) */ BUG_ON(current_cpu_type() != c->cputype); + if (cpu_has_rixi) { + /* Enable the RIXI exceptions */ + set_c0_pagegrain(PG_IEC); + back_to_back_c0_hazard(); + /* Verify the IEC bit is set */ + if (read_c0_pagegrain() & PG_IEC) + c->options |= MIPS_CPU_RIXIEX; + } + if (mips_fpu_disabled) c->options &= ~MIPS_CPU_FPU; -- cgit v1.2.3-59-g8ed1b From b47208091291ea2990b69eb59c72d04c7161303e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:53 -0800 Subject: MIPS: BMIPS: BMIPS4380 and BMIPS5000 support RIXI Make BMIPS4380 and BMIPS5000 advertise support for RIXI through cpu_probe_broadcom(). bmips_cpu_setup() needs to be called shortly after that, during prom_init() in order to enable the proper Broadcom-specific register to turn on RIXI and the "rotr" instruction. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12507/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 ++ arch/mips/kernel/cpu-probe.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5562ee535db8..ac9bfad794eb 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1832,6 +1832,7 @@ config CPU_BMIPS4380 select MIPS_L1_CACHE_SHIFT_6 select SYS_SUPPORTS_SMP select SYS_SUPPORTS_HOTPLUG_CPU + select CPU_HAS_RIXI config CPU_BMIPS5000 bool @@ -1839,6 +1840,7 @@ config CPU_BMIPS5000 select MIPS_L1_CACHE_SHIFT_7 select SYS_SUPPORTS_SMP select SYS_SUPPORTS_HOTPLUG_CPU + select CPU_HAS_RIXI config SYS_HAS_CPU_LOONGSON3 bool diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 4bcbf002a8f7..46a24729fbba 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1468,6 +1468,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_BMIPS4380; __cpu_name[cpu] = "Broadcom BMIPS4380"; set_elf_platform(cpu, "bmips4380"); + c->options |= MIPS_CPU_RIXI; } else { c->cputype = CPU_BMIPS4350; __cpu_name[cpu] = "Broadcom BMIPS4350"; @@ -1483,7 +1484,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) else __cpu_name[cpu] = "Broadcom BMIPS5000"; set_elf_platform(cpu, "bmips5000"); - c->options |= MIPS_CPU_ULRI; + c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI; break; } } -- cgit v1.2.3-59-g8ed1b From 8f4703aa4df758def78e9a39cc5d1ff73c3ef51f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 11 May 2016 00:50:03 +0200 Subject: MIPS: Octeon: detect and fix byte swapped initramfs Octeon machines support running in little endian mode. U-Boot usually runs in big endian-mode. Therefore the initramfs is loaded in big endian mode, and the kernel later tries to access it in little endian mode. This patch fixes that by detecting byte swapped initramfs using either the CPIO header or the header from standard compression methods, and byte swaps it if needed. It first checks that the header doesn't match in the native endianness to avoid false detections. It uses the kernel decompress library so that we don't have to maintain the list of magics if some decompression methods are added to the kernel. Signed-off-by: Aurelien Jarno Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13219/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 19c03a9e7492..ef408a03e818 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,35 @@ disable: return 0; } +/* In some conditions (e.g. big endian bootloader with a little endian + kernel), the initrd might appear byte swapped. Try to detect this and + byte swap it if needed. */ +static void __init maybe_bswap_initrd(void) +{ +#if defined(CONFIG_CPU_CAVIUM_OCTEON) + u64 buf; + + /* Check for CPIO signature */ + if (!memcmp((void *)initrd_start, "070701", 6)) + return; + + /* Check for compressed initrd */ + if (decompress_method((unsigned char *)initrd_start, 8, NULL)) + return; + + /* Try again with a byte swapped header */ + buf = swab64p((u64 *)initrd_start); + if (!memcmp(&buf, "070701", 6) || + decompress_method((unsigned char *)(&buf), 8, NULL)) { + unsigned long i; + + pr_info("Byteswapped initrd detected\n"); + for (i = initrd_start; i < ALIGN(initrd_end, 8); i += 8) + swab64s((u64 *)i); + } +#endif +} + static void __init finalize_initrd(void) { unsigned long size = initrd_end - initrd_start; @@ -256,6 +286,8 @@ static void __init finalize_initrd(void) goto disable; } + maybe_bswap_initrd(); + reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); initrd_below_start_ok = 1; -- cgit v1.2.3-59-g8ed1b From 9c938a0df074d4100de38ff967b97451f9b9ae7e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:33:21 -0700 Subject: MIPS: ath79: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Cc: Antony Pavlov Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13133/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 3cfc5ecddddf..2e7378467c5c 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -44,7 +44,7 @@ static struct clk *__init ath79_add_sys_clkdev( struct clk *clk; int err; - clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate); + clk = clk_register_fixed_rate(NULL, id, NULL, 0, rate); if (!clk) panic("failed to allocate %s clock structure", id); -- cgit v1.2.3-59-g8ed1b From dc3ee608d6f16947b812c7fac33c18863acdc074 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:34:37 -0700 Subject: MIPS: alchemy: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Cc: Manuel Lauss Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13134/ Signed-off-by: Ralf Baechle --- arch/mips/alchemy/common/clock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index bd34f4093cd9..7ba7ea0a22f8 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -1043,8 +1043,7 @@ static int __init alchemy_clk_init(void) /* Root of the Alchemy clock tree: external 12MHz crystal osc */ c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL, - CLK_IS_ROOT, - ALCHEMY_ROOTCLK_RATE); + 0, ALCHEMY_ROOTCLK_RATE); ERRCK(c) /* CPU core clock */ -- cgit v1.2.3-59-g8ed1b From 37af2f3077d9202f8f8d17f453c91c9d08e11c76 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:49 +0100 Subject: MIPS: Define & use CP0_EBase bit definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add definitions for the bits & fields in the CP0_EBase register, and use them from a few different places in arch/mips which hardcoded these values. Signed-off-by: James Hogan Cc: Jayachandran C Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13222/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 10 +++++++++- arch/mips/kvm/trap_emul.c | 3 ++- arch/mips/netlogic/xlp/nlm_hal.c | 2 +- arch/mips/netlogic/xlr/setup.c | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index b7705ef09df2..57d72f2bf745 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -676,6 +676,14 @@ #define MIPS_MAAR_S (_ULCAST_(1) << 1) #define MIPS_MAAR_V (_ULCAST_(1) << 0) +/* EBase bit definitions */ +#define MIPS_EBASE_CPUNUM_SHIFT 0 +#define MIPS_EBASE_CPUNUM (_ULCAST_(0x3ff) << 0) +#define MIPS_EBASE_WG_SHIFT 11 +#define MIPS_EBASE_WG (_ULCAST_(1) << 11) +#define MIPS_EBASE_BASE_SHIFT 12 +#define MIPS_EBASE_BASE (~_ULCAST_((1 << MIPS_EBASE_BASE_SHIFT) - 1)) + /* CMGCRBase bit definitions */ #define MIPS_CMGCRB_BASE 11 #define MIPS_CMGCRF_BASE (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1)) @@ -2104,7 +2112,7 @@ __BUILD_SET_C0(brcm_mode) */ static inline unsigned int get_ebase_cpunum(void) { - return read_c0_ebase() & 0x3ff; + return read_c0_ebase() & MIPS_EBASE_CPUNUM; } #endif /* !__ASSEMBLY__ */ diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index c4038d2a724c..fd43f0afdb9f 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c @@ -505,7 +505,8 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu) kvm_write_c0_guest_intctl(cop0, 0xFC000000); /* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */ - kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF)); + kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | + (vcpu_id & MIPS_EBASE_CPUNUM)); return 0; } diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 80ec929747c3..25ee69489e5e 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -58,7 +58,7 @@ void nlm_node_init(int node) nodep->coremask = 1; /* node 0, boot cpu */ nodep->sysbase = nlm_get_sys_regbase(node); nodep->picbase = nlm_get_pic_regbase(node); - nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; if (cpu_is_xlp9xx()) nodep->socbus = xlp9xx_get_socbus(node); else diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index d118b9aa7647..72ceddc9a03f 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -168,7 +168,7 @@ static void nlm_init_node(void) nodep = nlm_current_node(); nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET); - nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; spin_lock_init(&nodep->piclock); } -- cgit v1.2.3-59-g8ed1b From 37fb60f8e3f011c25c120081a73886ad8dbc42fd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:50 +0100 Subject: MIPS: Add defs & probing of extended CP0_EBase The CP0_EBase register may optionally have a write gate (WG) bit to allow the upper bits to be written, i.e. bits 31:30 on MIPS32 since r3 (to allow for an exception base outside of KSeg0/KSeg1 when segmentation control is in use) and bits 63:30 on MIPS64 (which also implies the extension of CP0_EBase to 64 bits long). The presence of this feature will need to be known about for VZ support in order to correctly save and restore all the bits of the guest CP0_EBase register, so add CPU feature definition and probing for this feature. Probing the WG bit on MIPS64 can be a bit fiddly, since 64-bit COP0 register access instructions were UNDEFINED for 32-bit registers prior to MIPS r6, and it'd be nice to be able to probe without clobbering the existing state, so there are 3 potential paths: - If we do a 32-bit read of CP0_EBase and the WG bit is already set, the register must be 64-bit. - On MIPS r6 we can do a 64-bit read-modify-write to set CP0_EBase.WG, since the upper bits will read 0 and be ignored on write if the register is 32-bit. - On pre-r6 cores, we do a 32-bit read-modify-write of CP0_EBase. This avoids the potentially UNDEFINED behaviour, but will clobber the upper 32-bits of CP0_EBase if it isn't a simple sign extension (which also requires us to ensure BEV=1 or modifying the exception base would be UNDEFINED too). It is hopefully unlikely a bootloader would set up CP0_EBase to a 64-bit segment and leave WG=0. [ralf@linux-mips.org: Resolved merge conflict.] Signed-off-by: James Hogan Tested-by: Matt Redfearn Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13223/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 3 +++ arch/mips/kernel/cpu-probe.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index bff73c52b273..676a37b9c37e 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -438,4 +438,8 @@ #define cpu_has_nan_2008 (cpu_data[0].options & MIPS_CPU_NAN_2008) #endif +#ifndef cpu_has_ebase_wg +# define cpu_has_ebase_wg (cpu_data[0].options & MIPS_CPU_EBASE_WG) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index f6cecc52a8c6..3108d9b35bf1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -404,6 +404,7 @@ enum cpu_type_enum { #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ #define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ +#define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 57d72f2bf745..4e8ad9d6038a 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1458,6 +1458,9 @@ do { \ #define read_c0_ebase() __read_32bit_c0_register($15, 1) #define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) +#define read_c0_ebase_64() __read_64bit_c0_register($15, 1) +#define write_c0_ebase_64(val) __write_64bit_c0_register($15, 1, val) + #define read_c0_cdmmbase() __read_ulong_c0_register($15, 2) #define write_c0_cdmmbase(val) __write_ulong_c0_register($15, 2, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 46a24729fbba..6a1a7da4b2d2 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -860,6 +860,41 @@ static void decode_configs(struct cpuinfo_mips *c) if (ok) ok = decode_config5(c); + /* Probe the EBase.WG bit */ + if (cpu_has_mips_r2_r6) { + u64 ebase; + unsigned int status; + + /* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */ + ebase = cpu_has_mips64r6 ? read_c0_ebase_64() + : (s32)read_c0_ebase(); + if (ebase & MIPS_EBASE_WG) { + /* WG bit already set, we can avoid the clumsy probe */ + c->options |= MIPS_CPU_EBASE_WG; + } else { + /* Its UNDEFINED to change EBase while BEV=0 */ + status = read_c0_status(); + write_c0_status(status | ST0_BEV); + irq_enable_hazard(); + /* + * On pre-r6 cores, this may well clobber the upper bits + * of EBase. This is hard to avoid without potentially + * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit. + */ + if (cpu_has_mips64r6) + write_c0_ebase_64(ebase | MIPS_EBASE_WG); + else + write_c0_ebase(ebase | MIPS_EBASE_WG); + back_to_back_c0_hazard(); + /* Restore BEV */ + write_c0_status(status); + if (read_c0_ebase() & MIPS_EBASE_WG) { + c->options |= MIPS_CPU_EBASE_WG; + write_c0_ebase(ebase); + } + } + } + mips_probe_watch_registers(c); #ifndef CONFIG_MIPS_CPS -- cgit v1.2.3-59-g8ed1b From e06a1548f3043febb658b58ec5ccbc7d03a785af Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:51 +0100 Subject: MIPS: Add defs & probing of BadInstr[P] registers The optional CP0_BadInstr and CP0_BadInstrP registers are written with the encoding of the instruction that caused a synchronous exception to occur, and the prior branch instruction if in a delay slot. These will be useful for instruction emulation in KVM, and especially for VZ support where reading guest virtual memory is a bit more awkward. Add CPU option numbers and cpu_has_* definitions to indicate the presence of each registers, and add code to probe for them using bits in the CP0_Config3 register. [ralf@linux-mips.org: resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13224/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 8 ++++++++ arch/mips/include/asm/cpu.h | 2 ++ arch/mips/include/asm/mipsregs.h | 3 +++ arch/mips/kernel/cpu-probe.c | 4 ++++ 4 files changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 676a37b9c37e..5d82b01ef8b5 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -442,4 +442,12 @@ # define cpu_has_ebase_wg (cpu_data[0].options & MIPS_CPU_EBASE_WG) #endif +#ifndef cpu_has_badinstr +# define cpu_has_badinstr (cpu_data[0].options & MIPS_CPU_BADINSTR) +#endif + +#ifndef cpu_has_badinstrp +# define cpu_has_badinstrp (cpu_data[0].options & MIPS_CPU_BADINSTRP) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 3108d9b35bf1..0cf90d67c1af 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -405,6 +405,8 @@ enum cpu_type_enum { #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ #define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ #define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ +#define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ +#define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 4e8ad9d6038a..b1f8f8436fd1 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1248,6 +1248,9 @@ do { \ #define read_c0_badvaddr() __read_ulong_c0_register($8, 0) #define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val) +#define read_c0_badinstr() __read_32bit_c0_register($8, 1) +#define read_c0_badinstrp() __read_32bit_c0_register($8, 2) + #define read_c0_count() __read_32bit_c0_register($9, 0) #define write_c0_count(val) __write_32bit_c0_register($9, 0, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 6a1a7da4b2d2..8e54d51c14bc 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -714,6 +714,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->ases |= MIPS_ASE_VZ; if (config3 & MIPS_CONF3_SC) c->options |= MIPS_CPU_SEGMENTS; + if (config3 & MIPS_CONF3_BI) + c->options |= MIPS_CPU_BADINSTR; + if (config3 & MIPS_CONF3_BP) + c->options |= MIPS_CPU_BADINSTRP; if (config3 & MIPS_CONF3_MSA) c->ases |= MIPS_ASE_MSA; if (config3 & MIPS_CONF3_PW) { -- cgit v1.2.3-59-g8ed1b From f18bdfa191df3947879f93519ce4a4985e5f5fce Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:52 +0100 Subject: MIPS: Add defs & probing of [X]ContextConfig The CP0_[X]ContextConfig registers are present if CP0_Config3.CTXTC or CP0_Config3.SM are set, and provide more control over which bits of CP0_[X]Context are set to the faulting virtual address on a TLB exception. KVM/VZ will need to be able to save and restore these registers in the guest context, so add the relevant definitions and probing of the ContextConfig feature in the root context first. [ralf@linux-mips.org: resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13225/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 6 ++++++ arch/mips/kernel/cpu-probe.c | 4 +++- 4 files changed, 14 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 5d82b01ef8b5..7962b257cc16 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -450,4 +450,8 @@ # define cpu_has_badinstrp (cpu_data[0].options & MIPS_CPU_BADINSTRP) #endif +#ifndef cpu_has_contextconfig +# define cpu_has_contextconfig (cpu_data[0].options & MIPS_CPU_CTXTC) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 0cf90d67c1af..ddcb2abd44ba 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -407,6 +407,7 @@ enum cpu_type_enum { #define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ #define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ +#define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index b1f8f8436fd1..08864cbbb27b 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1228,9 +1228,15 @@ do { \ #define read_c0_context() __read_ulong_c0_register($4, 0) #define write_c0_context(val) __write_ulong_c0_register($4, 0, val) +#define read_c0_contextconfig() __read_32bit_c0_register($4, 1) +#define write_c0_contextconfig(val) __write_32bit_c0_register($4, 1, val) + #define read_c0_userlocal() __read_ulong_c0_register($4, 2) #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) +#define read_c0_xcontextconfig() __read_ulong_c0_register($4, 3) +#define write_c0_xcontextconfig(val) __write_ulong_c0_register($4, 3, val) + #define read_c0_pagemask() __read_32bit_c0_register($5, 0) #define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8e54d51c14bc..963ce7ef29df 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -687,10 +687,12 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) if (config3 & MIPS_CONF3_SM) { c->ases |= MIPS_ASE_SMARTMIPS; - c->options |= MIPS_CPU_RIXI; + c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC; } if (config3 & MIPS_CONF3_RXI) c->options |= MIPS_CPU_RIXI; + if (config3 & MIPS_CONF3_CTXTC) + c->options |= MIPS_CPU_CTXTC; if (config3 & MIPS_CONF3_DSP) c->ases |= MIPS_ASE_DSP; if (config3 & MIPS_CONF3_DSP2P) { -- cgit v1.2.3-59-g8ed1b From 30228c40f0c6f0a93910325f120904505a4c39cc Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:53 +0100 Subject: MIPS: Add perf counter feature Add CPU feature for standard MIPS r2 performance counters, as determined by the Config1.PC bit. Both perf_events and oprofile probe this bit, so lets combine the probing and change both to use cpu_has_perf. This will also be used for VZ support in KVM to know whether performance counters exist which can be exposed to guests. [ralf@linux-mips.org: resolve conflict.] Signed-off-by: James Hogan Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Robert Richter Cc: linux-mips@linux-mips.org Cc: oprofile-list@lists.sf.net Patchwork: https://patchwork.linux-mips.org/patch/13226/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/kernel/cpu-probe.c | 2 ++ arch/mips/kernel/perf_event_mipsxx.c | 4 +--- arch/mips/oprofile/op_model_mipsxx.c | 4 +--- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 7962b257cc16..232b0377346a 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -454,4 +454,8 @@ # define cpu_has_contextconfig (cpu_data[0].options & MIPS_CPU_CTXTC) #endif +#ifndef cpu_has_perf +# define cpu_has_perf (cpu_data[0].options & MIPS_CPU_PERF) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index ddcb2abd44ba..3971a25e07a6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -408,6 +408,7 @@ enum cpu_type_enum { #define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ #define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ +#define MIPS_CPU_PERF MBIT_ULL(47) /* CPU has MIPS performance counters */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 963ce7ef29df..45770d83c3f0 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -648,6 +648,8 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c) if (config1 & MIPS_CONF1_MD) c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_PC) + c->options |= MIPS_CPU_PERF; if (config1 & MIPS_CONF1_WR) c->options |= MIPS_CPU_WATCH; if (config1 & MIPS_CONF1_CA) diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 656769c166fc..302af8c975df 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -101,8 +101,6 @@ struct mips_pmu { static struct mips_pmu mipspmu; -#define M_CONFIG1_PC (1 << 4) - #define M_PERFCTL_EXL (1 << 0) #define M_PERFCTL_KERNEL (1 << 1) #define M_PERFCTL_SUPERVISOR (1 << 2) @@ -754,7 +752,7 @@ static void handle_associated_event(struct cpu_hw_events *cpuc, static int __n_counters(void) { - if (!(read_c0_config1() & M_CONFIG1_PC)) + if (!cpu_has_perf) return 0; if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) return 1; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 8f988a61b7a8..45cb27469fba 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void) return handled; } -#define M_CONFIG1_PC (1 << 4) - static inline int __n_counters(void) { - if (!(read_c0_config1() & M_CONFIG1_PC)) + if (!cpu_has_perf) return 0; if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) return 1; -- cgit v1.2.3-59-g8ed1b From 9e575f753576d85e83ae0afc27eca9708259a797 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:27 +0100 Subject: MIPS: Avoid magic numbers probing kscratch_mask The decode_config4() function reads kscratch_mask from CP0_Config4.KScrExist using a hard coded shift and mask. We already have a definition for the mask in mipsregs.h, so add a definition for the shift and make use of them. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13227/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 3 ++- arch/mips/kernel/cpu-probe.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 08864cbbb27b..480d51550dc0 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -615,7 +615,8 @@ #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) #define MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT (_ULCAST_(2) << 14) #define MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT (_ULCAST_(3) << 14) -#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << 16) +#define MIPS_CONF4_KSCREXIST_SHIFT (16) +#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << MIPS_CONF4_KSCREXIST_SHIFT) #define MIPS_CONF4_VTLBSIZEEXT_SHIFT (24) #define MIPS_CONF4_VTLBSIZEEXT (_ULCAST_(15) << MIPS_CONF4_VTLBSIZEEXT_SHIFT) #define MIPS_CONF4_AE (_ULCAST_(1) << 28) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 45770d83c3f0..31c27576a931 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -801,7 +801,8 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) } } - c->kscratch_mask = (config4 >> 16) & 0xff; + c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST) + >> MIPS_CONF4_KSCREXIST_SHIFT; asid_mask = MIPS_ENTRYHI_ASID; if (config4 & MIPS_CONF4_AE) -- cgit v1.2.3-59-g8ed1b From f913e9ea3946902f5443e703d70d5daf90f4498a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:28 +0100 Subject: MIPS: Add register definitions for VZ ASE registers Add various register definitions to for the coprocessor zero registers in the VZ ASE, namely CP0_GuestCtl0, CP0_GuestCtl0Ext, CP0_GuestCtl1, CP0_GuestCtl2, CP0_GuestCtl3, and CP0_GTOffset. Signed-off-by: James Hogan Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13228/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 480d51550dc0..951d92e5f771 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -55,8 +55,14 @@ #define CP0_BADINSTR $8, 1 #define CP0_COUNT $9 #define CP0_ENTRYHI $10 +#define CP0_GUESTCTL1 $10, 4 +#define CP0_GUESTCTL2 $10, 5 +#define CP0_GUESTCTL3 $10, 6 #define CP0_COMPARE $11 +#define CP0_GUESTCTL0EXT $11, 4 #define CP0_STATUS $12 +#define CP0_GUESTCTL0 $12, 6 +#define CP0_GTOFFSET $12, 7 #define CP0_CAUSE $13 #define CP0_EPC $14 #define CP0_PRID $15 @@ -740,6 +746,94 @@ #define MIPS_PWCTL_PSN_SHIFT 0 #define MIPS_PWCTL_PSN_MASK 0x0000003f +/* GuestCtl0 fields */ +#define MIPS_GCTL0_GM_SHIFT 31 +#define MIPS_GCTL0_GM (_ULCAST_(1) << MIPS_GCTL0_GM_SHIFT) +#define MIPS_GCTL0_RI_SHIFT 30 +#define MIPS_GCTL0_RI (_ULCAST_(1) << MIPS_GCTL0_RI_SHIFT) +#define MIPS_GCTL0_MC_SHIFT 29 +#define MIPS_GCTL0_MC (_ULCAST_(1) << MIPS_GCTL0_MC_SHIFT) +#define MIPS_GCTL0_CP0_SHIFT 28 +#define MIPS_GCTL0_CP0 (_ULCAST_(1) << MIPS_GCTL0_CP0_SHIFT) +#define MIPS_GCTL0_AT_SHIFT 26 +#define MIPS_GCTL0_AT (_ULCAST_(0x3) << MIPS_GCTL0_AT_SHIFT) +#define MIPS_GCTL0_GT_SHIFT 25 +#define MIPS_GCTL0_GT (_ULCAST_(1) << MIPS_GCTL0_GT_SHIFT) +#define MIPS_GCTL0_CG_SHIFT 24 +#define MIPS_GCTL0_CG (_ULCAST_(1) << MIPS_GCTL0_CG_SHIFT) +#define MIPS_GCTL0_CF_SHIFT 23 +#define MIPS_GCTL0_CF (_ULCAST_(1) << MIPS_GCTL0_CF_SHIFT) +#define MIPS_GCTL0_G1_SHIFT 22 +#define MIPS_GCTL0_G1 (_ULCAST_(1) << MIPS_GCTL0_G1_SHIFT) +#define MIPS_GCTL0_G0E_SHIFT 19 +#define MIPS_GCTL0_G0E (_ULCAST_(1) << MIPS_GCTL0_G0E_SHIFT) +#define MIPS_GCTL0_PT_SHIFT 18 +#define MIPS_GCTL0_PT (_ULCAST_(1) << MIPS_GCTL0_PT_SHIFT) +#define MIPS_GCTL0_RAD_SHIFT 9 +#define MIPS_GCTL0_RAD (_ULCAST_(1) << MIPS_GCTL0_RAD_SHIFT) +#define MIPS_GCTL0_DRG_SHIFT 8 +#define MIPS_GCTL0_DRG (_ULCAST_(1) << MIPS_GCTL0_DRG_SHIFT) +#define MIPS_GCTL0_G2_SHIFT 7 +#define MIPS_GCTL0_G2 (_ULCAST_(1) << MIPS_GCTL0_G2_SHIFT) +#define MIPS_GCTL0_GEXC_SHIFT 2 +#define MIPS_GCTL0_GEXC (_ULCAST_(0x1f) << MIPS_GCTL0_GEXC_SHIFT) +#define MIPS_GCTL0_SFC2_SHIFT 1 +#define MIPS_GCTL0_SFC2 (_ULCAST_(1) << MIPS_GCTL0_SFC2_SHIFT) +#define MIPS_GCTL0_SFC1_SHIFT 0 +#define MIPS_GCTL0_SFC1 (_ULCAST_(1) << MIPS_GCTL0_SFC1_SHIFT) + +/* GuestCtl0.AT Guest address translation control */ +#define MIPS_GCTL0_AT_ROOT 1 /* Guest MMU under Root control */ +#define MIPS_GCTL0_AT_GUEST 3 /* Guest MMU under Guest control */ + +/* GuestCtl0.GExcCode Hypervisor exception cause codes */ +#define MIPS_GCTL0_GEXC_GPSI 0 /* Guest Privileged Sensitive Instruction */ +#define MIPS_GCTL0_GEXC_GSFC 1 /* Guest Software Field Change */ +#define MIPS_GCTL0_GEXC_HC 2 /* Hypercall */ +#define MIPS_GCTL0_GEXC_GRR 3 /* Guest Reserved Instruction Redirect */ +#define MIPS_GCTL0_GEXC_GVA 8 /* Guest Virtual Address available */ +#define MIPS_GCTL0_GEXC_GHFC 9 /* Guest Hardware Field Change */ +#define MIPS_GCTL0_GEXC_GPA 10 /* Guest Physical Address available */ + +/* GuestCtl0Ext fields */ +#define MIPS_GCTL0EXT_RPW_SHIFT 8 +#define MIPS_GCTL0EXT_RPW (_ULCAST_(0x3) << MIPS_GCTL0EXT_RPW_SHIFT) +#define MIPS_GCTL0EXT_NCC_SHIFT 6 +#define MIPS_GCTL0EXT_NCC (_ULCAST_(0x3) << MIPS_GCTL0EXT_NCC_SHIFT) +#define MIPS_GCTL0EXT_CGI_SHIFT 4 +#define MIPS_GCTL0EXT_CGI (_ULCAST_(1) << MIPS_GCTL0EXT_CGI_SHIFT) +#define MIPS_GCTL0EXT_FCD_SHIFT 3 +#define MIPS_GCTL0EXT_FCD (_ULCAST_(1) << MIPS_GCTL0EXT_FCD_SHIFT) +#define MIPS_GCTL0EXT_OG_SHIFT 2 +#define MIPS_GCTL0EXT_OG (_ULCAST_(1) << MIPS_GCTL0EXT_OG_SHIFT) +#define MIPS_GCTL0EXT_BG_SHIFT 1 +#define MIPS_GCTL0EXT_BG (_ULCAST_(1) << MIPS_GCTL0EXT_BG_SHIFT) +#define MIPS_GCTL0EXT_MG_SHIFT 0 +#define MIPS_GCTL0EXT_MG (_ULCAST_(1) << MIPS_GCTL0EXT_MG_SHIFT) + +/* GuestCtl0Ext.RPW Root page walk configuration */ +#define MIPS_GCTL0EXT_RPW_BOTH 0 /* Root PW for GPA->RPA and RVA->RPA */ +#define MIPS_GCTL0EXT_RPW_GPA 2 /* Root PW for GPA->RPA */ +#define MIPS_GCTL0EXT_RPW_RVA 3 /* Root PW for RVA->RPA */ + +/* GuestCtl0Ext.NCC Nested cache coherency attributes */ +#define MIPS_GCTL0EXT_NCC_IND 0 /* Guest CCA independent of Root CCA */ +#define MIPS_GCTL0EXT_NCC_MOD 1 /* Guest CCA modified by Root CCA */ + +/* GuestCtl1 fields */ +#define MIPS_GCTL1_ID_SHIFT 0 +#define MIPS_GCTL1_ID_WIDTH 8 +#define MIPS_GCTL1_ID (_ULCAST_(0xff) << MIPS_GCTL1_ID_SHIFT) +#define MIPS_GCTL1_RID_SHIFT 16 +#define MIPS_GCTL1_RID_WIDTH 8 +#define MIPS_GCTL1_RID (_ULCAST_(0xff) << MIPS_GCTL1_RID_SHIFT) +#define MIPS_GCTL1_EID_SHIFT 24 +#define MIPS_GCTL1_EID_WIDTH 8 +#define MIPS_GCTL1_EID (_ULCAST_(0xff) << MIPS_GCTL1_EID_SHIFT) + +/* GuestID reserved for root context */ +#define MIPS_GCTL1_ROOT_GUESTID 0 + /* CDMMBase register bit definitions */ #define MIPS_CDMMBASE_SIZE_SHIFT 0 #define MIPS_CDMMBASE_SIZE (_ULCAST_(511) << MIPS_CDMMBASE_SIZE_SHIFT) @@ -1270,9 +1364,21 @@ do { \ #define read_c0_entryhi() __read_ulong_c0_register($10, 0) #define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) +#define read_c0_guestctl1() __read_32bit_c0_register($10, 4) +#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val) + +#define read_c0_guestctl2() __read_32bit_c0_register($10, 5) +#define write_c0_guestctl2(val) __write_32bit_c0_register($10, 5, val) + +#define read_c0_guestctl3() __read_32bit_c0_register($10, 6) +#define write_c0_guestctl3(val) __write_32bit_c0_register($10, 6, val) + #define read_c0_compare() __read_32bit_c0_register($11, 0) #define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) +#define read_c0_guestctl0ext() __read_32bit_c0_register($11, 4) +#define write_c0_guestctl0ext(val) __write_32bit_c0_register($11, 4, val) + #define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ #define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) @@ -1283,6 +1389,12 @@ do { \ #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) +#define read_c0_guestctl0() __read_32bit_c0_register($12, 6) +#define write_c0_guestctl0(val) __write_32bit_c0_register($12, 6, val) + +#define read_c0_gtoffset() __read_32bit_c0_register($12, 7) +#define write_c0_gtoffset(val) __write_32bit_c0_register($12, 7, val) + #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) @@ -2111,6 +2223,11 @@ __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) __BUILD_SET_C0(pagegrain) +__BUILD_SET_C0(guestctl0) +__BUILD_SET_C0(guestctl0ext) +__BUILD_SET_C0(guestctl1) +__BUILD_SET_C0(guestctl2) +__BUILD_SET_C0(guestctl3) __BUILD_SET_C0(brcm_config_0) __BUILD_SET_C0(brcm_bus_pll) __BUILD_SET_C0(brcm_reset) -- cgit v1.2.3-59-g8ed1b From 7eb91118227d71132ca2da06a9b376ba656171d9 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:29 +0100 Subject: MIPS: Add guest CP0 accessors Add guest CP0 accessors and guest TLB operations along the same lines as the existing macros and functions for the root CP0. Signed-off-by: James Hogan Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13229/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 341 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 330 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 951d92e5f771..1019de6bb2a8 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1679,6 +1679,253 @@ do { \ #define read_c0_brcm_sleepcount() __read_32bit_c0_register($22, 7) #define write_c0_brcm_sleepcount(val) __write_32bit_c0_register($22, 7, val) +/* + * Macros to access the guest system control coprocessor + */ + +#define __read_32bit_gc0_register(source, sel) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips32r2\n\t" \ + ".set\tvirt\n\t" \ + "mfgc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_gc0_register(source, sel) \ +({ unsigned long long __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips64r2\n\t" \ + ".set\tvirt\n\t" \ + "dmfgc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips32r2\n\t" \ + ".set\tvirt\n\t" \ + "mtgc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tpop" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +#define __write_64bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips64r2\n\t" \ + ".set\tvirt\n\t" \ + "dmtgc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tpop" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_gc0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + (unsigned long) __read_32bit_gc0_register(reg, sel) : \ + (unsigned long) __read_64bit_gc0_register(reg, sel)) + +#define __write_ulong_gc0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_gc0_register(reg, sel, val); \ + else \ + __write_64bit_gc0_register(reg, sel, val); \ +} while (0) + +#define read_gc0_index() __read_32bit_gc0_register($0, 0) +#define write_gc0_index(val) __write_32bit_gc0_register($0, 0, val) + +#define read_gc0_entrylo0() __read_ulong_gc0_register($2, 0) +#define write_gc0_entrylo0(val) __write_ulong_gc0_register($2, 0, val) + +#define read_gc0_entrylo1() __read_ulong_gc0_register($3, 0) +#define write_gc0_entrylo1(val) __write_ulong_gc0_register($3, 0, val) + +#define read_gc0_context() __read_ulong_gc0_register($4, 0) +#define write_gc0_context(val) __write_ulong_gc0_register($4, 0, val) + +#define read_gc0_contextconfig() __read_32bit_gc0_register($4, 1) +#define write_gc0_contextconfig(val) __write_32bit_gc0_register($4, 1, val) + +#define read_gc0_userlocal() __read_ulong_gc0_register($4, 2) +#define write_gc0_userlocal(val) __write_ulong_gc0_register($4, 2, val) + +#define read_gc0_xcontextconfig() __read_ulong_gc0_register($4, 3) +#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register($4, 3, val) + +#define read_gc0_pagemask() __read_32bit_gc0_register($5, 0) +#define write_gc0_pagemask(val) __write_32bit_gc0_register($5, 0, val) + +#define read_gc0_pagegrain() __read_32bit_gc0_register($5, 1) +#define write_gc0_pagegrain(val) __write_32bit_gc0_register($5, 1, val) + +#define read_gc0_segctl0() __read_ulong_gc0_register($5, 2) +#define write_gc0_segctl0(val) __write_ulong_gc0_register($5, 2, val) + +#define read_gc0_segctl1() __read_ulong_gc0_register($5, 3) +#define write_gc0_segctl1(val) __write_ulong_gc0_register($5, 3, val) + +#define read_gc0_segctl2() __read_ulong_gc0_register($5, 4) +#define write_gc0_segctl2(val) __write_ulong_gc0_register($5, 4, val) + +#define read_gc0_pwbase() __read_ulong_gc0_register($5, 5) +#define write_gc0_pwbase(val) __write_ulong_gc0_register($5, 5, val) + +#define read_gc0_pwfield() __read_ulong_gc0_register($5, 6) +#define write_gc0_pwfield(val) __write_ulong_gc0_register($5, 6, val) + +#define read_gc0_pwsize() __read_ulong_gc0_register($5, 7) +#define write_gc0_pwsize(val) __write_ulong_gc0_register($5, 7, val) + +#define read_gc0_wired() __read_32bit_gc0_register($6, 0) +#define write_gc0_wired(val) __write_32bit_gc0_register($6, 0, val) + +#define read_gc0_pwctl() __read_32bit_gc0_register($6, 6) +#define write_gc0_pwctl(val) __write_32bit_gc0_register($6, 6, val) + +#define read_gc0_hwrena() __read_32bit_gc0_register($7, 0) +#define write_gc0_hwrena(val) __write_32bit_gc0_register($7, 0, val) + +#define read_gc0_badvaddr() __read_ulong_gc0_register($8, 0) +#define write_gc0_badvaddr(val) __write_ulong_gc0_register($8, 0, val) + +#define read_gc0_badinstr() __read_32bit_gc0_register($8, 1) +#define write_gc0_badinstr(val) __write_32bit_gc0_register($8, 1, val) + +#define read_gc0_badinstrp() __read_32bit_gc0_register($8, 2) +#define write_gc0_badinstrp(val) __write_32bit_gc0_register($8, 2, val) + +#define read_gc0_count() __read_32bit_gc0_register($9, 0) + +#define read_gc0_entryhi() __read_ulong_gc0_register($10, 0) +#define write_gc0_entryhi(val) __write_ulong_gc0_register($10, 0, val) + +#define read_gc0_compare() __read_32bit_gc0_register($11, 0) +#define write_gc0_compare(val) __write_32bit_gc0_register($11, 0, val) + +#define read_gc0_status() __read_32bit_gc0_register($12, 0) +#define write_gc0_status(val) __write_32bit_gc0_register($12, 0, val) + +#define read_gc0_intctl() __read_32bit_gc0_register($12, 1) +#define write_gc0_intctl(val) __write_32bit_gc0_register($12, 1, val) + +#define read_gc0_cause() __read_32bit_gc0_register($13, 0) +#define write_gc0_cause(val) __write_32bit_gc0_register($13, 0, val) + +#define read_gc0_epc() __read_ulong_gc0_register($14, 0) +#define write_gc0_epc(val) __write_ulong_gc0_register($14, 0, val) + +#define read_gc0_ebase() __read_32bit_gc0_register($15, 1) +#define write_gc0_ebase(val) __write_32bit_gc0_register($15, 1, val) + +#define read_gc0_ebase_64() __read_64bit_gc0_register($15, 1) +#define write_gc0_ebase_64(val) __write_64bit_gc0_register($15, 1, val) + +#define read_gc0_config() __read_32bit_gc0_register($16, 0) +#define read_gc0_config1() __read_32bit_gc0_register($16, 1) +#define read_gc0_config2() __read_32bit_gc0_register($16, 2) +#define read_gc0_config3() __read_32bit_gc0_register($16, 3) +#define read_gc0_config4() __read_32bit_gc0_register($16, 4) +#define read_gc0_config5() __read_32bit_gc0_register($16, 5) +#define read_gc0_config6() __read_32bit_gc0_register($16, 6) +#define read_gc0_config7() __read_32bit_gc0_register($16, 7) +#define write_gc0_config(val) __write_32bit_gc0_register($16, 0, val) +#define write_gc0_config1(val) __write_32bit_gc0_register($16, 1, val) +#define write_gc0_config2(val) __write_32bit_gc0_register($16, 2, val) +#define write_gc0_config3(val) __write_32bit_gc0_register($16, 3, val) +#define write_gc0_config4(val) __write_32bit_gc0_register($16, 4, val) +#define write_gc0_config5(val) __write_32bit_gc0_register($16, 5, val) +#define write_gc0_config6(val) __write_32bit_gc0_register($16, 6, val) +#define write_gc0_config7(val) __write_32bit_gc0_register($16, 7, val) + +#define read_gc0_watchlo0() __read_ulong_gc0_register($18, 0) +#define read_gc0_watchlo1() __read_ulong_gc0_register($18, 1) +#define read_gc0_watchlo2() __read_ulong_gc0_register($18, 2) +#define read_gc0_watchlo3() __read_ulong_gc0_register($18, 3) +#define read_gc0_watchlo4() __read_ulong_gc0_register($18, 4) +#define read_gc0_watchlo5() __read_ulong_gc0_register($18, 5) +#define read_gc0_watchlo6() __read_ulong_gc0_register($18, 6) +#define read_gc0_watchlo7() __read_ulong_gc0_register($18, 7) +#define write_gc0_watchlo0(val) __write_ulong_gc0_register($18, 0, val) +#define write_gc0_watchlo1(val) __write_ulong_gc0_register($18, 1, val) +#define write_gc0_watchlo2(val) __write_ulong_gc0_register($18, 2, val) +#define write_gc0_watchlo3(val) __write_ulong_gc0_register($18, 3, val) +#define write_gc0_watchlo4(val) __write_ulong_gc0_register($18, 4, val) +#define write_gc0_watchlo5(val) __write_ulong_gc0_register($18, 5, val) +#define write_gc0_watchlo6(val) __write_ulong_gc0_register($18, 6, val) +#define write_gc0_watchlo7(val) __write_ulong_gc0_register($18, 7, val) + +#define read_gc0_watchhi0() __read_32bit_gc0_register($19, 0) +#define read_gc0_watchhi1() __read_32bit_gc0_register($19, 1) +#define read_gc0_watchhi2() __read_32bit_gc0_register($19, 2) +#define read_gc0_watchhi3() __read_32bit_gc0_register($19, 3) +#define read_gc0_watchhi4() __read_32bit_gc0_register($19, 4) +#define read_gc0_watchhi5() __read_32bit_gc0_register($19, 5) +#define read_gc0_watchhi6() __read_32bit_gc0_register($19, 6) +#define read_gc0_watchhi7() __read_32bit_gc0_register($19, 7) +#define write_gc0_watchhi0(val) __write_32bit_gc0_register($19, 0, val) +#define write_gc0_watchhi1(val) __write_32bit_gc0_register($19, 1, val) +#define write_gc0_watchhi2(val) __write_32bit_gc0_register($19, 2, val) +#define write_gc0_watchhi3(val) __write_32bit_gc0_register($19, 3, val) +#define write_gc0_watchhi4(val) __write_32bit_gc0_register($19, 4, val) +#define write_gc0_watchhi5(val) __write_32bit_gc0_register($19, 5, val) +#define write_gc0_watchhi6(val) __write_32bit_gc0_register($19, 6, val) +#define write_gc0_watchhi7(val) __write_32bit_gc0_register($19, 7, val) + +#define read_gc0_xcontext() __read_ulong_gc0_register($20, 0) +#define write_gc0_xcontext(val) __write_ulong_gc0_register($20, 0, val) + +#define read_gc0_perfctrl0() __read_32bit_gc0_register($25, 0) +#define write_gc0_perfctrl0(val) __write_32bit_gc0_register($25, 0, val) +#define read_gc0_perfcntr0() __read_32bit_gc0_register($25, 1) +#define write_gc0_perfcntr0(val) __write_32bit_gc0_register($25, 1, val) +#define read_gc0_perfcntr0_64() __read_64bit_gc0_register($25, 1) +#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register($25, 1, val) +#define read_gc0_perfctrl1() __read_32bit_gc0_register($25, 2) +#define write_gc0_perfctrl1(val) __write_32bit_gc0_register($25, 2, val) +#define read_gc0_perfcntr1() __read_32bit_gc0_register($25, 3) +#define write_gc0_perfcntr1(val) __write_32bit_gc0_register($25, 3, val) +#define read_gc0_perfcntr1_64() __read_64bit_gc0_register($25, 3) +#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register($25, 3, val) +#define read_gc0_perfctrl2() __read_32bit_gc0_register($25, 4) +#define write_gc0_perfctrl2(val) __write_32bit_gc0_register($25, 4, val) +#define read_gc0_perfcntr2() __read_32bit_gc0_register($25, 5) +#define write_gc0_perfcntr2(val) __write_32bit_gc0_register($25, 5, val) +#define read_gc0_perfcntr2_64() __read_64bit_gc0_register($25, 5) +#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register($25, 5, val) +#define read_gc0_perfctrl3() __read_32bit_gc0_register($25, 6) +#define write_gc0_perfctrl3(val) __write_32bit_gc0_register($25, 6, val) +#define read_gc0_perfcntr3() __read_32bit_gc0_register($25, 7) +#define write_gc0_perfcntr3(val) __write_32bit_gc0_register($25, 7, val) +#define read_gc0_perfcntr3_64() __read_64bit_gc0_register($25, 7) +#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register($25, 7, val) + +#define read_gc0_errorepc() __read_ulong_gc0_register($30, 0) +#define write_gc0_errorepc(val) __write_ulong_gc0_register($30, 0, val) + +#define read_gc0_kscratch1() __read_ulong_gc0_register($31, 2) +#define read_gc0_kscratch2() __read_ulong_gc0_register($31, 3) +#define read_gc0_kscratch3() __read_ulong_gc0_register($31, 4) +#define read_gc0_kscratch4() __read_ulong_gc0_register($31, 5) +#define read_gc0_kscratch5() __read_ulong_gc0_register($31, 6) +#define read_gc0_kscratch6() __read_ulong_gc0_register($31, 7) +#define write_gc0_kscratch1(val) __write_ulong_gc0_register($31, 2, val) +#define write_gc0_kscratch2(val) __write_ulong_gc0_register($31, 3, val) +#define write_gc0_kscratch3(val) __write_ulong_gc0_register($31, 4, val) +#define write_gc0_kscratch4(val) __write_ulong_gc0_register($31, 5, val) +#define write_gc0_kscratch5(val) __write_ulong_gc0_register($31, 6, val) +#define write_gc0_kscratch6(val) __write_ulong_gc0_register($31, 7, val) + /* * Macros to access the floating point coprocessor control registers */ @@ -2175,46 +2422,109 @@ static inline void tlb_write_random(void) } /* - * Manipulate bits in a c0 register. + * Guest TLB operations. + * + * It is responsibility of the caller to take care of any TLB hazards. + */ +static inline void guest_tlb_probe(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgp\n\t" + ".set pop"); +} + +static inline void guest_tlb_read(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgr\n\t" + ".set pop"); +} + +static inline void guest_tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgwi\n\t" + ".set pop"); +} + +static inline void guest_tlb_write_random(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgwr\n\t" + ".set pop"); +} + +/* + * Guest TLB Invalidate Flush */ -#define __BUILD_SET_C0(name) \ +static inline void guest_tlbinvf(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbginvf\n\t" + ".set pop"); +} + +/* + * Manipulate bits in a register. + */ +#define __BUILD_SET_COMMON(name) \ static inline unsigned int \ -set_c0_##name(unsigned int set) \ +set_##name(unsigned int set) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res | set; \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } \ \ static inline unsigned int \ -clear_c0_##name(unsigned int clear) \ +clear_##name(unsigned int clear) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res & ~clear; \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } \ \ static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int val) \ +change_##name(unsigned int change, unsigned int val) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res & ~change; \ new |= (val & change); \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } +/* + * Manipulate bits in a c0 register. + */ +#define __BUILD_SET_C0(name) __BUILD_SET_COMMON(c0_##name) + __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) @@ -2236,6 +2546,15 @@ __BUILD_SET_C0(brcm_cmt_ctrl) __BUILD_SET_C0(brcm_config) __BUILD_SET_C0(brcm_mode) +/* + * Manipulate bits in a guest c0 register. + */ +#define __BUILD_SET_GC0(name) __BUILD_SET_COMMON(gc0_##name) + +__BUILD_SET_GC0(status) +__BUILD_SET_GC0(cause) +__BUILD_SET_GC0(ebase) + /* * Return low 10 bits of ebase. * Note that under KVM (MIPSVZ) this returns vcpu id. -- cgit v1.2.3-59-g8ed1b From 6ad816e77ed77538fe729050cf6631328c6113f7 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:30 +0100 Subject: MIPS: Add probing & defs for VZ & guest features Add a few new cpu-features.h definitions for VZ sub-features, namely the existence of the CP0_GuestCtl0Ext, CP0_GuestCtl1, and CP0_GuestCtl2 registers, and support for GuestID to dialias TLB entries belonging to different guests. Also add certain features present in the guest, with the naming scheme cpu_guest_has_*. These are added separately to the main options bitfield since they generally parallel similar features in the root context. A few of these (FPU, MSA, watchpoints, perf counters, CP0_[X]ContextConfig registers, MAAR registers, and probably others in future) can be dynamically configured in the guest context, for which the cpu_guest_has_dyn_* macros are added. [ralf@linux-mips.org: Resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13231/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 98 +++++++++++++++ arch/mips/include/asm/cpu-info.h | 14 +++ arch/mips/include/asm/cpu.h | 5 + arch/mips/kernel/cpu-probe.c | 232 +++++++++++++++++++++++++++++++++++ 4 files changed, 349 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 232b0377346a..e6f19fc61bf2 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -120,6 +120,21 @@ #ifndef kernel_uses_llsc #define kernel_uses_llsc cpu_has_llsc #endif +#ifndef cpu_has_guestctl0ext +#define cpu_has_guestctl0ext (cpu_data[0].options & MIPS_CPU_GUESTCTL0EXT) +#endif +#ifndef cpu_has_guestctl1 +#define cpu_has_guestctl1 (cpu_data[0].options & MIPS_CPU_GUESTCTL1) +#endif +#ifndef cpu_has_guestctl2 +#define cpu_has_guestctl2 (cpu_data[0].options & MIPS_CPU_GUESTCTL2) +#endif +#ifndef cpu_has_guestid +#define cpu_has_guestid (cpu_data[0].options & MIPS_CPU_GUESTID) +#endif +#ifndef cpu_has_drg +#define cpu_has_drg (cpu_data[0].options & MIPS_CPU_DRG) +#endif #ifndef cpu_has_mips16 #define cpu_has_mips16 (cpu_data[0].ases & MIPS_ASE_MIPS16) #endif @@ -458,4 +473,87 @@ # define cpu_has_perf (cpu_data[0].options & MIPS_CPU_PERF) #endif +/* + * Guest capabilities + */ +#ifndef cpu_guest_has_conf1 +#define cpu_guest_has_conf1 (cpu_data[0].guest.conf & (1 << 1)) +#endif +#ifndef cpu_guest_has_conf2 +#define cpu_guest_has_conf2 (cpu_data[0].guest.conf & (1 << 2)) +#endif +#ifndef cpu_guest_has_conf3 +#define cpu_guest_has_conf3 (cpu_data[0].guest.conf & (1 << 3)) +#endif +#ifndef cpu_guest_has_conf4 +#define cpu_guest_has_conf4 (cpu_data[0].guest.conf & (1 << 4)) +#endif +#ifndef cpu_guest_has_conf5 +#define cpu_guest_has_conf5 (cpu_data[0].guest.conf & (1 << 5)) +#endif +#ifndef cpu_guest_has_conf6 +#define cpu_guest_has_conf6 (cpu_data[0].guest.conf & (1 << 6)) +#endif +#ifndef cpu_guest_has_conf7 +#define cpu_guest_has_conf7 (cpu_data[0].guest.conf & (1 << 7)) +#endif +#ifndef cpu_guest_has_fpu +#define cpu_guest_has_fpu (cpu_data[0].guest.options & MIPS_CPU_FPU) +#endif +#ifndef cpu_guest_has_watch +#define cpu_guest_has_watch (cpu_data[0].guest.options & MIPS_CPU_WATCH) +#endif +#ifndef cpu_guest_has_contextconfig +#define cpu_guest_has_contextconfig (cpu_data[0].guest.options & MIPS_CPU_CTXTC) +#endif +#ifndef cpu_guest_has_segments +#define cpu_guest_has_segments (cpu_data[0].guest.options & MIPS_CPU_SEGMENTS) +#endif +#ifndef cpu_guest_has_badinstr +#define cpu_guest_has_badinstr (cpu_data[0].guest.options & MIPS_CPU_BADINSTR) +#endif +#ifndef cpu_guest_has_badinstrp +#define cpu_guest_has_badinstrp (cpu_data[0].guest.options & MIPS_CPU_BADINSTRP) +#endif +#ifndef cpu_guest_has_htw +#define cpu_guest_has_htw (cpu_data[0].guest.options & MIPS_CPU_HTW) +#endif +#ifndef cpu_guest_has_msa +#define cpu_guest_has_msa (cpu_data[0].guest.ases & MIPS_ASE_MSA) +#endif +#ifndef cpu_guest_has_kscr +#define cpu_guest_has_kscr(n) (cpu_data[0].guest.kscratch_mask & (1u << (n))) +#endif +#ifndef cpu_guest_has_rw_llb +#define cpu_guest_has_rw_llb (cpu_has_mips_r6 || (cpu_data[0].guest.options & MIPS_CPU_RW_LLB)) +#endif +#ifndef cpu_guest_has_perf +#define cpu_guest_has_perf (cpu_data[0].guest.options & MIPS_CPU_PERF) +#endif +#ifndef cpu_guest_has_maar +#define cpu_guest_has_maar (cpu_data[0].guest.options & MIPS_CPU_MAAR) +#endif + +/* + * Guest dynamic capabilities + */ +#ifndef cpu_guest_has_dyn_fpu +#define cpu_guest_has_dyn_fpu (cpu_data[0].guest.options_dyn & MIPS_CPU_FPU) +#endif +#ifndef cpu_guest_has_dyn_watch +#define cpu_guest_has_dyn_watch (cpu_data[0].guest.options_dyn & MIPS_CPU_WATCH) +#endif +#ifndef cpu_guest_has_dyn_contextconfig +#define cpu_guest_has_dyn_contextconfig (cpu_data[0].guest.options_dyn & MIPS_CPU_CTXTC) +#endif +#ifndef cpu_guest_has_dyn_perf +#define cpu_guest_has_dyn_perf (cpu_data[0].guest.options_dyn & MIPS_CPU_PERF) +#endif +#ifndef cpu_guest_has_dyn_msa +#define cpu_guest_has_dyn_msa (cpu_data[0].guest.ases_dyn & MIPS_ASE_MSA) +#endif +#ifndef cpu_guest_has_dyn_maar +#define cpu_guest_has_dyn_maar (cpu_data[0].guest.options_dyn & MIPS_CPU_MAAR) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 392da7e6fc72..edbe2734a1bf 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -28,6 +28,15 @@ struct cache_desc { unsigned char flags; /* Flags describing cache properties */ }; +struct guest_info { + unsigned long ases; + unsigned long ases_dyn; + unsigned long long options; + unsigned long long options_dyn; + u8 conf; + u8 kscratch_mask; +}; + /* * Flag definitions */ @@ -95,6 +104,11 @@ struct cpuinfo_mips { * htw_start/htw_stop calls */ unsigned int htw_seq; + + /* VZ & Guest features */ + struct guest_info guest; + unsigned int gtoffset_mask; + unsigned int guestid_mask; } __attribute__((aligned(SMP_CACHE_BYTES))); extern struct cpuinfo_mips cpu_data[]; diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 3971a25e07a6..f672df8b26d0 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -409,6 +409,11 @@ enum cpu_type_enum { #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ #define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ #define MIPS_CPU_PERF MBIT_ULL(47) /* CPU has MIPS performance counters */ +#define MIPS_CPU_GUESTCTL0EXT MBIT_ULL(48) /* CPU has VZ GuestCtl0Ext register */ +#define MIPS_CPU_GUESTCTL1 MBIT_ULL(49) /* CPU has VZ GuestCtl1 register */ +#define MIPS_CPU_GUESTCTL2 MBIT_ULL(50) /* CPU has VZ GuestCtl2 register */ +#define MIPS_CPU_GUESTID MBIT_ULL(51) /* CPU uses VZ ASE GuestID feature */ +#define MIPS_CPU_DRG MBIT_ULL(52) /* CPU has VZ Direct Root to Guest (DRG) */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 31c27576a931..5ac5c3e23460 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -915,6 +915,235 @@ static void decode_configs(struct cpuinfo_mips *c) #endif } +/* + * Probe for certain guest capabilities by writing config bits and reading back. + * Finally write back the original value. + */ +#define probe_gc0_config(name, maxconf, bits) \ +do { \ + unsigned int tmp; \ + tmp = read_gc0_##name(); \ + write_gc0_##name(tmp | (bits)); \ + back_to_back_c0_hazard(); \ + maxconf = read_gc0_##name(); \ + write_gc0_##name(tmp); \ +} while (0) + +/* + * Probe for dynamic guest capabilities by changing certain config bits and + * reading back to see if they change. Finally write back the original value. + */ +#define probe_gc0_config_dyn(name, maxconf, dynconf, bits) \ +do { \ + maxconf = read_gc0_##name(); \ + write_gc0_##name(maxconf ^ (bits)); \ + back_to_back_c0_hazard(); \ + dynconf = maxconf ^ read_gc0_##name(); \ + write_gc0_##name(maxconf); \ + maxconf |= dynconf; \ +} while (0) + +static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + + probe_gc0_config(config, config0, MIPS_CONF_M); + + if (config0 & MIPS_CONF_M) + c->guest.conf |= BIT(1); + return config0 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c) +{ + unsigned int config1, config1_dyn; + + probe_gc0_config_dyn(config1, config1, config1_dyn, + MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR | + MIPS_CONF1_FP); + + if (config1 & MIPS_CONF1_FP) + c->guest.options |= MIPS_CPU_FPU; + if (config1_dyn & MIPS_CONF1_FP) + c->guest.options_dyn |= MIPS_CPU_FPU; + + if (config1 & MIPS_CONF1_WR) + c->guest.options |= MIPS_CPU_WATCH; + if (config1_dyn & MIPS_CONF1_WR) + c->guest.options_dyn |= MIPS_CPU_WATCH; + + if (config1 & MIPS_CONF1_PC) + c->guest.options |= MIPS_CPU_PERF; + if (config1_dyn & MIPS_CONF1_PC) + c->guest.options_dyn |= MIPS_CPU_PERF; + + if (config1 & MIPS_CONF_M) + c->guest.conf |= BIT(2); + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + probe_gc0_config(config2, config2, MIPS_CONF_M); + + if (config2 & MIPS_CONF_M) + c->guest.conf |= BIT(3); + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c) +{ + unsigned int config3, config3_dyn; + + probe_gc0_config_dyn(config3, config3, config3_dyn, + MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC); + + if (config3 & MIPS_CONF3_CTXTC) + c->guest.options |= MIPS_CPU_CTXTC; + if (config3_dyn & MIPS_CONF3_CTXTC) + c->guest.options_dyn |= MIPS_CPU_CTXTC; + + if (config3 & MIPS_CONF3_PW) + c->guest.options |= MIPS_CPU_HTW; + + if (config3 & MIPS_CONF3_SC) + c->guest.options |= MIPS_CPU_SEGMENTS; + + if (config3 & MIPS_CONF3_BI) + c->guest.options |= MIPS_CPU_BADINSTR; + if (config3 & MIPS_CONF3_BP) + c->guest.options |= MIPS_CPU_BADINSTRP; + + if (config3 & MIPS_CONF3_MSA) + c->guest.ases |= MIPS_ASE_MSA; + if (config3_dyn & MIPS_CONF3_MSA) + c->guest.ases_dyn |= MIPS_ASE_MSA; + + if (config3 & MIPS_CONF_M) + c->guest.conf |= BIT(4); + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + probe_gc0_config(config4, config4, + MIPS_CONF_M | MIPS_CONF4_KSCREXIST); + + c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST) + >> MIPS_CONF4_KSCREXIST_SHIFT; + + if (config4 & MIPS_CONF_M) + c->guest.conf |= BIT(5); + return config4 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c) +{ + unsigned int config5, config5_dyn; + + probe_gc0_config_dyn(config5, config5, config5_dyn, + MIPS_CONF_M | MIPS_CONF5_MRP); + + if (config5 & MIPS_CONF5_MRP) + c->guest.options |= MIPS_CPU_MAAR; + if (config5_dyn & MIPS_CONF5_MRP) + c->guest.options_dyn |= MIPS_CPU_MAAR; + + if (config5 & MIPS_CONF5_LLB) + c->guest.options |= MIPS_CPU_RW_LLB; + + if (config5 & MIPS_CONF_M) + c->guest.conf |= BIT(6); + return config5 & MIPS_CONF_M; +} + +static inline void decode_guest_configs(struct cpuinfo_mips *c) +{ + unsigned int ok; + + ok = decode_guest_config0(c); + if (ok) + ok = decode_guest_config1(c); + if (ok) + ok = decode_guest_config2(c); + if (ok) + ok = decode_guest_config3(c); + if (ok) + ok = decode_guest_config4(c); + if (ok) + decode_guest_config5(c); +} + +static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c) +{ + unsigned int guestctl0, temp; + + guestctl0 = read_c0_guestctl0(); + + if (guestctl0 & MIPS_GCTL0_G0E) + c->options |= MIPS_CPU_GUESTCTL0EXT; + if (guestctl0 & MIPS_GCTL0_G1) + c->options |= MIPS_CPU_GUESTCTL1; + if (guestctl0 & MIPS_GCTL0_G2) + c->options |= MIPS_CPU_GUESTCTL2; + if (!(guestctl0 & MIPS_GCTL0_RAD)) { + c->options |= MIPS_CPU_GUESTID; + + /* + * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0 + * first, otherwise all data accesses will be fully virtualised + * as if they were performed by guest mode. + */ + write_c0_guestctl1(0); + tlbw_use_hazard(); + + write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG); + back_to_back_c0_hazard(); + temp = read_c0_guestctl0(); + + if (temp & MIPS_GCTL0_DRG) { + write_c0_guestctl0(guestctl0); + c->options |= MIPS_CPU_DRG; + } + } +} + +static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c) +{ + if (cpu_has_guestid) { + /* determine the number of bits of GuestID available */ + write_c0_guestctl1(MIPS_GCTL1_ID); + back_to_back_c0_hazard(); + c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID) + >> MIPS_GCTL1_ID_SHIFT; + write_c0_guestctl1(0); + } +} + +static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c) +{ + /* determine the number of bits of GTOffset available */ + write_c0_gtoffset(0xffffffff); + back_to_back_c0_hazard(); + c->gtoffset_mask = read_c0_gtoffset(); + write_c0_gtoffset(0); +} + +static inline void cpu_probe_vz(struct cpuinfo_mips *c) +{ + cpu_probe_guestctl0(c); + if (cpu_has_guestctl1) + cpu_probe_guestctl1(c); + + cpu_probe_gtoffset(c); + + decode_guest_configs(c); +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -1817,6 +2046,9 @@ void cpu_probe(void) elf_hwcap |= HWCAP_MIPS_MSA; } + if (cpu_has_vz) + cpu_probe_vz(c); + cpu_probe_vmbits(c); #ifdef CONFIG_64BIT -- cgit v1.2.3-59-g8ed1b From 382208dc8c856b4d8ba602031412842b121decb2 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:31 +0100 Subject: MIPS: dump_tlb: Preserve and dump GuestID The GuestID for root TLB operations (GuestCtl1.RID) is modified by TLB reads, so needs preserving by dump_tlb() like the ASID field of EntryHi. Also dump the GuestID of each entry if it exists alongside the ASID, as it forms an important part of the TLB entry when VZ guests are used. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13230/ Signed-off-by: Ralf Baechle --- arch/mips/lib/dump_tlb.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 3283aa7423e4..2cb10dba8838 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -72,7 +72,8 @@ static void dump_tlb(int first, int last) { unsigned long s_entryhi, entryhi, asid; unsigned long long entrylo0, entrylo1, pa; - unsigned int s_index, s_pagemask, pagemask, c0, c1, i; + unsigned int s_index, s_pagemask, s_guestctl1 = 0; + unsigned int pagemask, guestctl1 = 0, c0, c1, i; unsigned long asidmask = cpu_asid_mask(¤t_cpu_data); int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4); #ifdef CONFIG_32BIT @@ -89,6 +90,8 @@ static void dump_tlb(int first, int last) s_entryhi = read_c0_entryhi(); s_index = read_c0_index(); asid = s_entryhi & asidmask; + if (cpu_has_guestid) + s_guestctl1 = read_c0_guestctl1(); for (i = first; i <= last; i++) { write_c0_index(i); @@ -99,6 +102,8 @@ static void dump_tlb(int first, int last) entryhi = read_c0_entryhi(); entrylo0 = read_c0_entrylo0(); entrylo1 = read_c0_entrylo1(); + if (cpu_has_guestid) + guestctl1 = read_c0_guestctl1(); /* EHINV bit marks entire entry as invalid */ if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV) @@ -128,15 +133,19 @@ static void dump_tlb(int first, int last) c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; - printk("va=%0*lx asid=%0*lx\n", + printk("va=%0*lx asid=%0*lx", vwidth, (entryhi & ~0x1fffUL), asidwidth, entryhi & asidmask); + if (cpu_has_guestid) + printk(" gid=%02lx", + (guestctl1 & MIPS_GCTL1_RID) + >> MIPS_GCTL1_RID_SHIFT); /* RI/XI are in awkward places, so mask them off separately */ pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); if (xpa) pa |= (unsigned long long)readx_c0_entrylo0() << 30; pa = (pa << 6) & PAGE_MASK; - printk("\t["); + printk("\n\t["); if (cpu_has_rixi) printk("ri=%d xi=%d ", (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, @@ -166,6 +175,8 @@ static void dump_tlb(int first, int last) write_c0_entryhi(s_entryhi); write_c0_index(s_index); write_c0_pagemask(s_pagemask); + if (cpu_has_guestid) + write_c0_guestctl1(s_guestctl1); } void dump_tlb_all(void) -- cgit v1.2.3-59-g8ed1b From 4b62fad50efd1cff9017d3e4dcfcf5c4b6c13193 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:32 +0100 Subject: MIPS: Print GuestCtl1 on machine check exception The GuestCtl1 CP0 register can contain the GuestID used for root TLB operations, which affects TLB matching. The other TLB registers are already dumped out to the log on a machine check exception due to multiple matching TLB entries, so also dump the value of the GuestCtl1 register if GuestIDs are supported. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13232/ Signed-off-by: Ralf Baechle --- arch/mips/lib/dump_tlb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 2cb10dba8838..0f80b936e75e 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -19,6 +19,8 @@ void dump_tlb_regs(void) pr_info("Index : %0x\n", read_c0_index()); pr_info("PageMask : %0x\n", read_c0_pagemask()); + if (cpu_has_guestid) + pr_info("GuestCtl1: %0x\n", read_c0_guestctl1()); pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi()); pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0()); pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1()); -- cgit v1.2.3-59-g8ed1b From de704161aa05a594fcd596cb7f50e231c384355e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:20:16 +0100 Subject: MIPS: ELF: Deconditionalise ABI flags definitions Move the `mips_elf_abiflags_v0' structure and FP ABI flag macros outside #ifndef ELF_ARCH. These are public interfaces. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13243/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 1fba19747fa9..94fd11953128 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -175,16 +175,14 @@ #define SHF_MIPS_NAMES 0x02000000 #define SHF_MIPS_NODUPES 0x01000000 -#ifndef ELF_ARCH -/* ELF register definitions */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned long elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */ +#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */ +#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */ +#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */ +#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */ +#define MIPS_ABI_FP_XX 5 /* -mfpxx */ +#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */ +#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */ struct mips_elf_abiflags_v0 { uint16_t version; /* Version of flags structure */ @@ -201,14 +199,16 @@ struct mips_elf_abiflags_v0 { uint32_t flags2; }; -#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */ -#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */ -#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */ -#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */ -#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */ -#define MIPS_ABI_FP_XX 5 /* -mfpxx */ -#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */ -#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */ +#ifndef ELF_ARCH +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #ifdef CONFIG_32BIT -- cgit v1.2.3-59-g8ed1b From 4a60ad51d660200adcb8bfecda472f0179ff22ec Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:20:55 +0100 Subject: MIPS: ELF: Unify __MIPS_O32_FP64_MUST_BE_ZERO definitions Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13244/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 25 ++++++++++++------------- arch/mips/kernel/binfmt_elfo32.c | 12 ------------ 2 files changed, 12 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 94fd11953128..68705a0a8014 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -211,19 +211,6 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #ifdef CONFIG_32BIT - -/* - * In order to be sure that we don't attempt to execute an O32 binary which - * requires 64 bit FP (FR=1) on a system which does not support it we refuse - * to execute any binary which has bits specified by the following macro set - * in its ELF header flags. - */ -#ifdef CONFIG_MIPS_O32_FP64_SUPPORT -# define __MIPS_O32_FP64_MUST_BE_ZERO 0 -#else -# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 -#endif - /* * This is used to ensure we don't load something for the wrong architecture. */ @@ -290,6 +277,18 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #endif /* !defined(ELF_ARCH) */ +/* + * In order to be sure that we don't attempt to execute an O32 binary which + * requires 64 bit FP (FR=1) on a system which does not support it we refuse + * to execute any binary which has bits specified by the following macro set + * in its ELF header flags. + */ +#ifdef CONFIG_MIPS_O32_FP64_SUPPORT +# define __MIPS_O32_FP64_MUST_BE_ZERO 0 +#else +# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 +#endif + #define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS) #define vmcore_elf32_check_arch mips_elf_check_machine diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index abd3affe5fb3..ca43eaf1734b 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -27,18 +27,6 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -/* - * In order to be sure that we don't attempt to execute an O32 binary which - * requires 64 bit FP (FR=1) on a system which does not support it we refuse - * to execute any binary which has bits specified by the following macro set - * in its ELF header flags. - */ -#ifdef CONFIG_MIPS_O32_FP64_SUPPORT -# define __MIPS_O32_FP64_MUST_BE_ZERO 0 -#else -# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 -#endif - /* * This is used to ensure we don't load something for the wrong architecture. */ -- cgit v1.2.3-59-g8ed1b From c9babb1926852d88ebee3c27f2b8bac848560c0e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:21:40 +0100 Subject: MIPS: ELF: Unify ABI classification macros Remove a duplicate o32 `elf_check_arch' implementation, move all macro variants to and define them unconditionally under indvidual names, substituting alias `elf_check_arch' definitions in variant code. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13245/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 91 ++++++++++++++++++++++++++-------------- arch/mips/kernel/binfmt_elfn32.c | 16 +------ arch/mips/kernel/binfmt_elfo32.c | 20 +-------- 3 files changed, 62 insertions(+), 65 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 68705a0a8014..f5f45717968e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -214,25 +214,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ - __res = 0; \ - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfo32_check_arch /* * These are used to set parameters in the core dumps. @@ -245,18 +227,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfn64_check_arch /* * These are used to set parameters in the core dumps. @@ -294,6 +265,64 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define vmcore_elf32_check_arch mips_elf_check_machine #define vmcore_elf64_check_arch mips_elf_check_machine +/* + * Return non-zero if HDR identifies an o32 ELF binary. + */ +#define elfo32_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ + __res = 0; \ + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * Return non-zero if HDR identifies an n64 ELF binary. + */ +#define elfn64_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * Return non-zero if HDR identifies an n32 ELF binary. + */ +#define elfn32_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ + ((__h->e_flags & EF_MIPS_ABI) != 0)) \ + __res = 0; \ + \ + __res; \ +}) + struct mips_abi; extern struct mips_abi mips_abi; diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index 1b992c6e3d8e..58ad63d7eb42 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -30,21 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ - ((__h->e_flags & EF_MIPS_ABI) != 0)) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfn32_check_arch #define TASK32_SIZE 0x7fff8000UL #undef ELF_ET_DYN_BASE diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index ca43eaf1734b..49fb881481f7 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -30,25 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ - __res = 0; \ - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfo32_check_arch #ifdef CONFIG_KVM_GUEST #define TASK32_SIZE 0x3fff8000UL -- cgit v1.2.3-59-g8ed1b From 9125f19bbb97e7444b5ea01f8262fa09679e1376 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 13 May 2016 13:22:41 +0530 Subject: MIPS: dts: pic32: Update dts to reflect new PIC32MZDA clk binding - now clock nodes definition is merged with core .dtsi file - only one rootclk is now part of DT - clock clients also updated based on new binding doc Signed-off-by: Purna Chandra Mandal Signed-off-by: Joshua Henderson Cc: Michael Turquette Cc: Stephen Boyd Cc: Kumar Gala Cc: Ian Campbell Cc: Rob Herring Cc: Pawel Moll Cc: Sandeep Sheriker Cc: Mark Rutland Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-clk@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13248/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi | 236 ---------------------------- arch/mips/boot/dts/pic32/pic32mzda.dtsi | 63 +++++--- arch/mips/boot/dts/pic32/pic32mzda_sk.dts | 5 +- 3 files changed, 45 insertions(+), 259 deletions(-) delete mode 100644 arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi (limited to 'arch') diff --git a/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi b/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi deleted file mode 100644 index ef1335012f43..000000000000 --- a/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Device Tree Source for PIC32MZDA clock data - * - * Purna Chandra Mandal - * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. - * - * Licensed under GPLv2 or later. - */ - -/* all fixed rate clocks */ - -/ { - POSC:posc_clk { /* On-chip primary oscillator */ - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <24000000>; - }; - - FRC:frc_clk { /* internal FRC oscillator */ - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <8000000>; - }; - - BFRC:bfrc_clk { /* internal backup FRC oscillator */ - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <8000000>; - }; - - LPRC:lprc_clk { /* internal low-power FRC oscillator */ - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32000>; - }; - - /* UPLL provides clock to USBCORE */ - UPLL:usb_phy_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "usbphy_clk"; - }; - - TxCKI:txcki_clk { /* external clock input on TxCLKI pin */ - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <4000000>; - status = "disabled"; - }; - - /* external clock input on REFCLKIx pin */ - REFIx:refix_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <24000000>; - status = "disabled"; - }; - - /* PIC32 specific clks */ - pic32_clktree { - #address-cells = <1>; - #size-cells = <1>; - reg = <0x1f801200 0x200>; - compatible = "microchip,pic32mzda-clk"; - ranges = <0 0x1f801200 0x200>; - - /* secondary oscillator; external input on SOSCI pin */ - SOSC:sosc_clk@0 { - #clock-cells = <0>; - compatible = "microchip,pic32mzda-sosc"; - clock-frequency = <32768>; - reg = <0x000 0x10>, /* enable reg */ - <0x1d0 0x10>; /* status reg */ - microchip,bit-mask = <0x02>; /* enable mask */ - microchip,status-bit-mask = <0x10>; /* status-mask*/ - }; - - FRCDIV:frcdiv_clk { - #clock-cells = <0>; - compatible = "microchip,pic32mzda-frcdivclk"; - clocks = <&FRC>; - clock-output-names = "frcdiv_clk"; - }; - - /* System PLL clock */ - SYSPLL:spll_clk@020 { - #clock-cells = <0>; - compatible = "microchip,pic32mzda-syspll"; - reg = <0x020 0x10>, /* SPLL register */ - <0x1d0 0x10>; /* CLKSTAT register */ - clocks = <&POSC>, <&FRC>; - clock-output-names = "sys_pll"; - microchip,status-bit-mask = <0x80>; /* SPLLRDY */ - }; - - /* system clock; mux with postdiv & slew */ - SYSCLK:sys_clk@1c0 { - #clock-cells = <0>; - compatible = "microchip,pic32mzda-sysclk-v2"; - reg = <0x1c0 0x04>; /* SLEWCON */ - clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>, - <&LPRC>, <&FRCDIV>; - microchip,clock-indices = <0>, <1>, <2>, <4>, - <5>, <7>; - clock-output-names = "sys_clk"; - }; - - /* Peripheral bus1 clock */ - PBCLK1:pb1_clk@140 { - reg = <0x140 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - clock-output-names = "pb1_clk"; - /* used by system modules, not gateable */ - microchip,ignore-unused; - }; - - /* Peripheral bus2 clock */ - PBCLK2:pb2_clk@150 { - reg = <0x150 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - clock-output-names = "pb2_clk"; - /* avoid gating even if unused */ - microchip,ignore-unused; - }; - - /* Peripheral bus3 clock */ - PBCLK3:pb3_clk@160 { - reg = <0x160 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - clock-output-names = "pb3_clk"; - }; - - /* Peripheral bus4 clock(I/O ports, GPIO) */ - PBCLK4:pb4_clk@170 { - reg = <0x170 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - clock-output-names = "pb4_clk"; - }; - - /* Peripheral bus clock */ - PBCLK5:pb5_clk@180 { - reg = <0x180 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - clock-output-names = "pb5_clk"; - }; - - /* Peripheral Bus6 clock; */ - PBCLK6:pb6_clk@190 { - reg = <0x190 0x10>; - compatible = "microchip,pic32mzda-pbclk"; - clocks = <&SYSCLK>; - #clock-cells = <0>; - }; - - /* Peripheral bus7 clock */ - PBCLK7:pb7_clk@1a0 { - reg = <0x1a0 0x10>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-pbclk"; - /* CPU is driven by this clock; so named */ - clock-output-names = "cpu_clk"; - clocks = <&SYSCLK>; - }; - - /* Reference Oscillator clock for SPI/I2S */ - REFCLKO1:refo1_clk@80 { - reg = <0x080 0x20>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-refoclk"; - clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>, - <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>; - microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, - <5>, <7>, <8>, <9>; - clock-output-names = "refo1_clk"; - }; - - /* Reference Oscillator clock for SQI */ - REFCLKO2:refo2_clk@a0 { - reg = <0x0a0 0x20>; - #clock-cells = <0>; - compatible = "microchip,pic32mzda-refoclk"; - clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>, - <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>; - microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, - <5>, <7>, <8>, <9>; - clock-output-names = "refo2_clk"; - }; - - /* Reference Oscillator clock, ADC */ - REFCLKO3:refo3_clk@c0 { - reg = <0x0c0 0x20>; - compatible = "microchip,pic32mzda-refoclk"; - clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>, - <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>; - microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, - <5>, <7>, <8>, <9>; - #clock-cells = <0>; - clock-output-names = "refo3_clk"; - }; - - /* Reference Oscillator clock */ - REFCLKO4:refo4_clk@e0 { - reg = <0x0e0 0x20>; - compatible = "microchip,pic32mzda-refoclk"; - clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>, - <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>; - microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, - <5>, <7>, <8>, <9>; - #clock-cells = <0>; - clock-output-names = "refo4_clk"; - }; - - /* Reference Oscillator clock, LCD */ - REFCLKO5:refo5_clk@100 { - reg = <0x100 0x20>; - compatible = "microchip,pic32mzda-refoclk"; - clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>, - <&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>; - microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, - <5>, <7>, <8>, <9>; - #clock-cells = <0>; - clock-output-names = "refo5_clk"; - }; - }; -}; diff --git a/arch/mips/boot/dts/pic32/pic32mzda.dtsi b/arch/mips/boot/dts/pic32/pic32mzda.dtsi index ad9e3318c2ce..5353a639c4fb 100644 --- a/arch/mips/boot/dts/pic32/pic32mzda.dtsi +++ b/arch/mips/boot/dts/pic32/pic32mzda.dtsi @@ -6,11 +6,9 @@ * published by the Free Software Foundation. * */ - +#include #include -#include "pic32mzda-clk.dtsi" - / { #address-cells = <1>; #size-cells = <1>; @@ -50,6 +48,29 @@ interrupts = <0 IRQ_TYPE_EDGE_RISING>; }; + /* external clock input on TxCLKI pin */ + txcki: txcki_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + status = "disabled"; + }; + + /* external input on REFCLKIx pin */ + refix: refix_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + status = "disabled"; + }; + + rootclk: clock-controller@1f801200 { + compatible = "microchip,pic32mzda-clk"; + reg = <0x1f801200 0x200>; + #clock-cells = <1>; + microchip,pic32mzda-sosc; + }; + evic: interrupt-controller@1f810000 { compatible = "microchip,pic32mzda-evic"; interrupt-controller; @@ -63,7 +84,7 @@ #size-cells = <1>; compatible = "microchip,pic32mzda-pinctrl"; reg = <0x1f801400 0x400>; - clocks = <&PBCLK1>; + clocks = <&rootclk PB1CLK>; }; /* PORTA */ @@ -75,7 +96,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <0>; gpio-ranges = <&pic32_pinctrl 0 0 16>; }; @@ -89,7 +110,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <1>; gpio-ranges = <&pic32_pinctrl 0 16 16>; }; @@ -103,7 +124,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <2>; gpio-ranges = <&pic32_pinctrl 0 32 16>; }; @@ -117,7 +138,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <3>; gpio-ranges = <&pic32_pinctrl 0 48 16>; }; @@ -131,7 +152,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <4>; gpio-ranges = <&pic32_pinctrl 0 64 16>; }; @@ -145,7 +166,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <5>; gpio-ranges = <&pic32_pinctrl 0 80 16>; }; @@ -159,7 +180,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <6>; gpio-ranges = <&pic32_pinctrl 0 96 16>; }; @@ -173,7 +194,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <7>; gpio-ranges = <&pic32_pinctrl 0 112 16>; }; @@ -189,7 +210,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <8>; gpio-ranges = <&pic32_pinctrl 0 128 16>; }; @@ -203,7 +224,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; - clocks = <&PBCLK4>; + clocks = <&rootclk PB4CLK>; microchip,gpio-bank = <9>; gpio-ranges = <&pic32_pinctrl 0 144 16>; }; @@ -212,7 +233,7 @@ compatible = "microchip,pic32mzda-sdhci"; reg = <0x1f8ec000 0x100>; interrupts = <191 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&REFCLKO4>, <&PBCLK5>; + clocks = <&rootclk REF4CLK>, <&rootclk PB5CLK>; clock-names = "base_clk", "sys_clk"; bus-width = <4>; cap-sd-highspeed; @@ -225,7 +246,7 @@ interrupts = <112 IRQ_TYPE_LEVEL_HIGH>, <113 IRQ_TYPE_LEVEL_HIGH>, <114 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; @@ -235,7 +256,7 @@ interrupts = <145 IRQ_TYPE_LEVEL_HIGH>, <146 IRQ_TYPE_LEVEL_HIGH>, <147 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; @@ -245,7 +266,7 @@ interrupts = <157 IRQ_TYPE_LEVEL_HIGH>, <158 IRQ_TYPE_LEVEL_HIGH>, <159 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; @@ -255,7 +276,7 @@ interrupts = <170 IRQ_TYPE_LEVEL_HIGH>, <171 IRQ_TYPE_LEVEL_HIGH>, <172 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; @@ -265,7 +286,7 @@ interrupts = <179 IRQ_TYPE_LEVEL_HIGH>, <180 IRQ_TYPE_LEVEL_HIGH>, <181 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; @@ -275,7 +296,7 @@ interrupts = <188 IRQ_TYPE_LEVEL_HIGH>, <189 IRQ_TYPE_LEVEL_HIGH>, <190 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&PBCLK2>; + clocks = <&rootclk PB2CLK>; status = "disabled"; }; }; diff --git a/arch/mips/boot/dts/pic32/pic32mzda_sk.dts b/arch/mips/boot/dts/pic32/pic32mzda_sk.dts index 5d434a50e85b..fc740102852e 100644 --- a/arch/mips/boot/dts/pic32/pic32mzda_sk.dts +++ b/arch/mips/boot/dts/pic32/pic32mzda_sk.dts @@ -95,8 +95,9 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdhc1>; status = "okay"; - assigned-clocks = <&REFCLKO2>,<&REFCLKO4>,<&REFCLKO5>; - assigned-clock-rates = <50000000>,<25000000>,<40000000>; + assigned-clocks = <&rootclk REF2CLK>, <&rootclk REF4CLK>, + <&rootclk REF5CLK>; + assigned-clock-rates = <50000000>, <25000000>, <40000000>; }; &pic32_pinctrl { -- cgit v1.2.3-59-g8ed1b From 4249548454f7ba4581aeee26bd83f42b48a14d15 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Thu, 12 May 2016 10:18:27 +0100 Subject: MIPS: ptrace: Fix FP context restoration FCSR regression Fix a floating-point context restoration regression introduced with commit 9b26616c8d9d ("MIPS: Respect the ISA level in FCSR handling") that causes a Floating Point exception and consequently a kernel oops with hard float configurations when one or more FCSR Enable and their corresponding Cause bits are set both at a time via a ptrace(2) call. To do so reinstate Cause bit masking originally introduced with commit b1442d39fac2 ("MIPS: Prevent user from setting FCSR cause bits") to address this exact problem and then inadvertently removed from the PTRACE_SETFPREGS request with the commit referred above. Signed-off-by: Maciej W. Rozycki Cc: stable@vger.kernel.org # v4.0+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13238/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 48c0534c4d15..88a1920669d5 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -176,6 +176,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) } __get_user(value, data + 64); + value &= ~FPU_CSR_ALL_X; fcr31 = child->thread.fpu.fcr31; mask = boot_cpu_data.fpu_msk31; child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); -- cgit v1.2.3-59-g8ed1b From abf378be49f38c4d3e23581d3df3fa9f1b1b11d2 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Thu, 12 May 2016 10:19:08 +0100 Subject: MIPS: ptrace: Prevent writes to read-only FCSR bits Correct the cases missed with commit 9b26616c8d9d ("MIPS: Respect the ISA level in FCSR handling") and prevent writes to read-only FCSR bits there. This in particular applies to FP context initialisation where any IEEE 754-2008 bits preset by `mips_set_personality_nan' are cleared before the relevant ptrace(2) call takes effect and the PTRACE_POKEUSR request addressing FPC_CSR where no masking of read-only FCSR bits is done. Remove the FCSR clearing from FP context initialisation then and unify PTRACE_POKEUSR/FPC_CSR and PTRACE_SETFPREGS handling, by factoring out code from `ptrace_setfpregs' and calling it from both places. This mostly matters to soft float configurations where the emulator can be switched this way to a mode which should not be accessible and cannot be set with the CTC1 instruction. With hard float configurations any effect is transient anyway as read-only bits will retain their values at the time the FP context is restored. Signed-off-by: Maciej W. Rozycki Cc: stable@vger.kernel.org # v4.0+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13239/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 88a1920669d5..0dcf69194473 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_struct *target) /* Begin with data registers set to all 1s... */ memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr)); - /* ...and FCSR zeroed */ - target->thread.fpu.fcr31 = 0; + /* FCSR has been preset by `mips_set_personality_nan'. */ /* * Record that the target has "used" math, such that the context @@ -79,6 +78,22 @@ void ptrace_disable(struct task_struct *child) clear_tsk_thread_flag(child, TIF_LOAD_WATCH); } +/* + * Poke at FCSR according to its mask. Don't set the cause bits as + * this is currently not handled correctly in FP context restoration + * and will cause an oops if a corresponding enable bit is set. + */ +static void ptrace_setfcr31(struct task_struct *child, u32 value) +{ + u32 fcr31; + u32 mask; + + value &= ~FPU_CSR_ALL_X; + fcr31 = child->thread.fpu.fcr31; + mask = boot_cpu_data.fpu_msk31; + child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); +} + /* * Read a general register set. We always use the 64-bit format, even * for 32-bit kernels and for 32-bit processes on a 64-bit kernel. @@ -159,9 +174,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) { union fpureg *fregs; u64 fpr_val; - u32 fcr31; u32 value; - u32 mask; int i; if (!access_ok(VERIFY_READ, data, 33 * 8)) @@ -176,10 +189,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) } __get_user(value, data + 64); - value &= ~FPU_CSR_ALL_X; - fcr31 = child->thread.fpu.fcr31; - mask = boot_cpu_data.fpu_msk31; - child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); + ptrace_setfcr31(child, value); /* FIR may not be written. */ @@ -807,7 +817,7 @@ long arch_ptrace(struct task_struct *child, long request, break; #endif case FPC_CSR: - child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X; + ptrace_setfcr31(child, data); break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; -- cgit v1.2.3-59-g8ed1b From e70ac023f9515c70cf2b291a294f0f250df29847 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 12:25:38 +0100 Subject: MIPS: Allow emulation for unaligned [LS]DXC1 instructions If an address error exception occurs for a LDXC1 or SDXC1 instruction, within the cop1x opcode space, allow it to be passed through to the FPU emulator rather than resulting in a SIGILL. This causes LDXC1 & SDXC1 to be handled in a manner consistent with the more common LDC1 & SDC1 instructions. Signed-off-by: Paul Burton Tested-by: Aurelien Jarno Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13143/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/unaligned.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 5c62065cbf22..28b3af73a17b 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -1191,6 +1191,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, case ldc1_op: case swc1_op: case sdc1_op: + case cop1x_op: die_if_kernel("Unaligned FP access in kernel code", regs); BUG_ON(!used_math()); -- cgit v1.2.3-59-g8ed1b From bd239f1e1429e7781096bf3884bdb1b2b1bb4f28 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 12:43:57 +0100 Subject: MIPS: Disable preemption during prctl(PR_SET_FP_MODE, ...) Whilst a PR_SET_FP_MODE prctl is performed there are decisions made based upon whether the task is executing on the current CPU. This may change if we're preempted, so disable preemption to avoid such changes for the lifetime of the mode switch. Signed-off-by: Paul Burton Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS") Reviewed-by: Maciej W. Rozycki Tested-by: Aurelien Jarno Cc: Adam Buchbinder Cc: James Hogan Cc: stable # v4.0+ Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13144/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index f57891616357..dcccc6dc68e6 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -597,6 +597,9 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6) return -EOPNOTSUPP; + /* Proceed with the mode switch */ + preempt_disable(); + /* Save FP & vector context, then disable FPU & MSA */ if (task->signal == current->signal) lose_fpu(1); @@ -655,6 +658,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) /* Allow threads to use FP again */ atomic_set(&task->mm->context.fp_mode_switching, 0); + preempt_enable(); return 0; } -- cgit v1.2.3-59-g8ed1b From 6b8322576e9d325b65c54fbef64e4e8690ad70ce Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 12:43:58 +0100 Subject: MIPS: Force CPUs to lose FP context during mode switches Commit 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS") added support for the PR_SET_FP_MODE prctl, which allows a userland program to modify its FP mode at runtime. This is most notably required if dynamic linking leads to the FP mode requirement changing at runtime from that indicated in the initial executable's ELF header. In order to avoid overhead in the general FP context restore code, it aimed to have threads in the process become unable to enable the FPU during a mode switch & have the thread calling the prctl syscall wait for all other threads in the process to be context switched at least once. Once that happens we can know that no thread in the process whose mode will be switched has live FP context, and it's safe to perform the mode switch. However in the (rare) case of modeswitches occurring in multithreaded programs this can lead to indeterminate delays for the thread invoking the prctl syscall, and the code monitoring for those context switches was woefully inadequate for all but the simplest cases. Fix this by broadcasting an IPI if other CPUs may have live FP context for an affected thread, with a handler causing those CPUs to relinquish their FPU ownership. Threads will then be allowed to continue running but will stall on the wait_on_atomic_t in enable_restore_fp_context if they attempt to use FP again whilst the mode switch is still in progress. The end result is less fragile poking at scheduler context switch counts & a more expedient completion of the mode switch. Signed-off-by: Paul Burton Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS") Reviewed-by: Maciej W. Rozycki Cc: Adam Buchbinder Cc: James Hogan Cc: stable # v4.0+ Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13145/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index dcccc6dc68e6..a6b3dc54260a 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -576,11 +576,19 @@ int mips_get_process_fp_mode(struct task_struct *task) return value; } +static void prepare_for_fp_mode_switch(void *info) +{ + struct mm_struct *mm = info; + + if (current->mm == mm) + lose_fpu(1); +} + int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) { const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE; - unsigned long switch_count; struct task_struct *t; + int max_users; /* Check the value is valid */ if (value & ~known_bits) @@ -609,31 +617,17 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) smp_mb__after_atomic(); /* - * If there are multiple online CPUs then wait until all threads whose - * FP mode is about to change have been context switched. This approach - * allows us to only worry about whether an FP mode switch is in - * progress when FP is first used in a tasks time slice. Pretty much all - * of the mode switch overhead can thus be confined to cases where mode - * switches are actually occurring. That is, to here. However for the - * thread performing the mode switch it may take a while... + * If there are multiple online CPUs then force any which are running + * threads in this process to lose their FPU context, which they can't + * regain until fp_mode_switching is cleared later. */ if (num_online_cpus() > 1) { - spin_lock_irq(&task->sighand->siglock); - - for_each_thread(task, t) { - if (t == current) - continue; - - switch_count = t->nvcsw + t->nivcsw; - - do { - spin_unlock_irq(&task->sighand->siglock); - cond_resched(); - spin_lock_irq(&task->sighand->siglock); - } while ((t->nvcsw + t->nivcsw) == switch_count); - } + /* No need to send an IPI for the local CPU */ + max_users = (task->mm == current->mm) ? 1 : 0; - spin_unlock_irq(&task->sighand->siglock); + if (atomic_read(¤t->mm->mm_users) > max_users) + smp_call_function(prepare_for_fp_mode_switch, + (void *)current->mm, 1); } /* -- cgit v1.2.3-59-g8ed1b From aab4673b599d8037c713afce40fabae398ca96c4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 22 Apr 2016 18:19:14 +0100 Subject: MIPS: malta-time: Start GIC count before syncing to RTC The sampling of the GIC counter on Malta after observing a rising edge of the RTC update flag differs slightly between the first and second sample, with the first sample also calling gic_start_count(). The two samples should really be taken as similarly as possible to get the most accurate figure, so move the gic_start_count() call before detecting the rising edge. Signed-off-by: James Hogan Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13173/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-time.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index b7bf721eabf5..2539687b77f6 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -81,16 +81,16 @@ static void __init estimate_frequencies(void) local_irq_save(flags); - /* Start counter exactly on falling edge of update flag. */ + if (gic_present) + gic_start_count(); + + /* Read counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - /* Initialize counters. */ start = read_c0_count(); - if (gic_present) { - gic_start_count(); + if (gic_present) gicstart = gic_read_count(); - } /* Read counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); -- cgit v1.2.3-59-g8ed1b From 24e1df664fd3c025664ae0b64a4aec691507959a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 22 Apr 2016 18:19:15 +0100 Subject: MIPS: malta-time: Take seconds into account When estimating the clock frequency based on the RTC, take seconds into account in case the Update In Progress (UIP) bit wasn't seen. This can happen in virtual machines (which may get pre-empted by the hypervisor at inopportune times) with QEMU emulating the RTC (and in fact not setting the UIP bit for very long), especially on slow hosts such as FPGA systems and hardware emulators. This results in several seconds actually having elapsed before seeing the UIP bit instead of just one second, and exaggerated timer frequencies. While updating the comments, they're also fixed to match the code in that the rising edge of the update flag is detected first, not the falling edge. The rising edge gives a more precise point to read the counters in a virtualised system than the falling edge, resulting in a more accurate frequency. It does however mean that we have to also wait for the falling edge before doing the read of the RTC seconds register, otherwise it seems to be possible in slow hardware emulation to stray into the interval when the RTC time is undefined during the update (at least 244uS after the rising edge of the update flag). This can result in both seconds values reading the same, and it wrapping to 60 seconds, vastly underestimating the frequency. Signed-off-by: James Hogan Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13174/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-time.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 2539687b77f6..7407da04f8d6 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,8 @@ static void __init estimate_frequencies(void) { unsigned long flags; unsigned int count, start; + unsigned char secs1, secs2, ctrl; + int secs; cycle_t giccount = 0, gicstart = 0; #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ @@ -84,29 +87,48 @@ static void __init estimate_frequencies(void) if (gic_present) gic_start_count(); - /* Read counter exactly on falling edge of update flag. */ + /* + * Read counters exactly on rising edge of update flag. + * This helps get an accurate reading under virtualisation. + */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - start = read_c0_count(); if (gic_present) gicstart = gic_read_count(); - /* Read counter exactly on falling edge of update flag. */ + /* Wait for falling edge before reading RTC. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); - while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + secs1 = CMOS_READ(RTC_SECONDS); + /* Read counters again exactly on rising edge of update flag. */ + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); count = read_c0_count(); if (gic_present) giccount = gic_read_count(); + /* Wait for falling edge before reading RTC again. */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + secs2 = CMOS_READ(RTC_SECONDS); + + ctrl = CMOS_READ(RTC_CONTROL); + local_irq_restore(flags); + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + secs1 = bcd2bin(secs1); + secs2 = bcd2bin(secs2); + } + secs = secs2 - secs1; + if (secs < 1) + secs += 60; + count -= start; + count /= secs; mips_hpt_frequency = count; if (gic_present) { - giccount -= gicstart; + giccount = div_u64(giccount - gicstart, secs); gic_frequency = giccount; } } -- cgit v1.2.3-59-g8ed1b From 1fa405552e33f2169d173cdb7ca0c03e094904f6 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 22 Apr 2016 18:19:17 +0100 Subject: MIPS: cevt-r4k: Dynamically calculate min_delta_ns Calculate the MIPS clockevent device's min_delta_ns dynamically based on the time it takes to perform the mips_next_event() sequence. Virtualisation in particular makes the current fixed min_delta of 0x300 inappropriate under some circumstances, as the CP0_Count and CP0_Compare registers may be being emulated by the hypervisor, and the frequency may not correspond directly to the CPU frequency. We actually use twice the median of multiple 75th percentiles of multiple measurements of how long the mips_next_event() sequence takes, in order to fairly efficiently eliminate outliers due to unexpected hypervisor latency (which would need handling with retries when it occurs during normal operation anyway). Signed-off-by: James Hogan Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13176/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cevt-r4k.c | 82 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 8dfe6a6e1480..e4c21bbf9422 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -28,6 +28,83 @@ static int mips_next_event(unsigned long delta, return res; } +/** + * calculate_min_delta() - Calculate a good minimum delta for mips_next_event(). + * + * Running under virtualisation can introduce overhead into mips_next_event() in + * the form of hypervisor emulation of CP0_Count/CP0_Compare registers, + * potentially with an unnatural frequency, which makes a fixed min_delta_ns + * value inappropriate as it may be too small. + * + * It can also introduce occasional latency from the guest being descheduled. + * + * This function calculates a good minimum delta based roughly on the 75th + * percentile of the time taken to do the mips_next_event() sequence, in order + * to handle potentially higher overhead while also eliminating outliers due to + * unpredictable hypervisor latency (which can be handled by retries). + * + * Return: An appropriate minimum delta for the clock event device. + */ +static unsigned int calculate_min_delta(void) +{ + unsigned int cnt, i, j, k, l; + unsigned int buf1[4], buf2[3]; + unsigned int min_delta; + + /* + * Calculate the median of 5 75th percentiles of 5 samples of how long + * it takes to set CP0_Compare = CP0_Count + delta. + */ + for (i = 0; i < 5; ++i) { + for (j = 0; j < 5; ++j) { + /* + * This is like the code in mips_next_event(), and + * directly measures the borderline "safe" delta. + */ + cnt = read_c0_count(); + write_c0_compare(cnt); + cnt = read_c0_count() - cnt; + + /* Sorted insert into buf1 */ + for (k = 0; k < j; ++k) { + if (cnt < buf1[k]) { + l = min_t(unsigned int, + j, ARRAY_SIZE(buf1) - 1); + for (; l > k; --l) + buf1[l] = buf1[l - 1]; + break; + } + } + if (k < ARRAY_SIZE(buf1)) + buf1[k] = cnt; + } + + /* Sorted insert of 75th percentile into buf2 */ + for (k = 0; k < i; ++k) { + if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) { + l = min_t(unsigned int, + i, ARRAY_SIZE(buf2) - 1); + for (; l > k; --l) + buf2[l] = buf2[l - 1]; + break; + } + } + if (k < ARRAY_SIZE(buf2)) + buf2[k] = buf1[ARRAY_SIZE(buf1) - 1]; + } + + /* Use 2 * median of 75th percentiles */ + min_delta = buf2[ARRAY_SIZE(buf2) - 1] * 2; + + /* Don't go too low */ + if (min_delta < 0x300) + min_delta = 0x300; + + pr_debug("%s: median 75th percentile=%#x, min_delta=%#x\n", + __func__, buf2[ARRAY_SIZE(buf2) - 1], min_delta); + return min_delta; +} + DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); int cp0_timer_irq_installed; @@ -177,7 +254,7 @@ int r4k_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; - unsigned int irq; + unsigned int irq, min_delta; if (!cpu_has_counter || !mips_hpt_frequency) return -ENXIO; @@ -203,7 +280,8 @@ int r4k_clockevent_init(void) /* Calculate the min / max delta */ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + min_delta = calculate_min_delta(); + cd->min_delta_ns = clockevent_delta2ns(min_delta, cd); cd->rating = 300; cd->irq = irq; -- cgit v1.2.3-59-g8ed1b From 6533af4d4831c421cd9aa4dce7cfc19a3514cc09 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 18:04:53 +0100 Subject: MIPS: Prevent "restoration" of MSA context in non-MSA kernels If a kernel doesn't support MSA context (ie. CONFIG_CPU_HAS_MSA=n) then it will only keep 64 bits per FP register in thread context, and the calls to set_fpr64 in restore_msa_extcontext will overrun the end of the FP register context into the FCSR & MSACSR values. GCC 6.x has become smart enough to detect this & complain like so: arch/mips/kernel/signal.c: In function 'protected_restore_fp_context': ./arch/mips/include/asm/processor.h:114:17: error: array subscript is above array bounds [-Werror=array-bounds] fpr->val##width[FPR_IDX(width, idx)] = val; \ ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ ./arch/mips/include/asm/processor.h:118:1: note: in expansion of macro 'BUILD_FPR_ACCESS' BUILD_FPR_ACCESS(64) The only way to trigger this code to run would be for a program to set up an artificial extended MSA context structure following a sigframe & execute sigreturn. Whilst this doesn't allow a program to write to any state that it couldn't already, it makes little sense to allow this "restoration" of MSA context in a system that doesn't support MSA. Fix this by killing a program with SIGSYS if it tries something as crazy as "restoring" fake MSA context in this way, also fixing the build error & allowing for most of restore_msa_extcontext to be optimised out of kernels without support for MSA. Signed-off-by: Paul Burton Reported-by: Michal Toman Fixes: bf82cb30c7e5 ("MIPS: Save MSA extended context around signals") Tested-by: Aaro Koskinen Cc: James Hogan Cc: Michal Toman Cc: linux-mips@linux-mips.org Cc: stable # v4.3+ Patchwork: https://patchwork.linux-mips.org/patch/13164/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/signal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 5f18d0b879e0..ab042291fbfd 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -195,6 +195,9 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size) unsigned int csr; int i, err; + if (!config_enabled(CONFIG_CPU_HAS_MSA)) + return SIGSYS; + if (size != sizeof(*msa)) return -EINVAL; @@ -398,8 +401,8 @@ int protected_restore_fp_context(void __user *sc) } fp_done: - if (used & USED_EXTCONTEXT) - err |= restore_extcontext(sc_to_extcontext(sc)); + if (!err && (used & USED_EXTCONTEXT)) + err = restore_extcontext(sc_to_extcontext(sc)); return err ?: sig; } -- cgit v1.2.3-59-g8ed1b From 86ce9a340e38bcba664fb11c7ab9ba03fcf5e55e Mon Sep 17 00:00:00 2001 From: Sashka Nochkin Date: Tue, 19 Apr 2016 23:44:45 -0400 Subject: mips: mt7620: fallback to SDRAM when syscfg0 does not have a valid value for the memory type Mediatek MT7620 SoC has syscfg0 bits where it sets the type of memory being used. However, sometimes those bits are not set properly (reading "11"). In this case, the SoC assumes SDRAM. The patch below reflects that. Signed-off-by: Sashka Nochkin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13135/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ralink/mt7620.h | 1 + arch/mips/ralink/mt7620.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index ece7420f6562..a73350b07fdf 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -72,6 +72,7 @@ #define SYSCFG0_DRAM_TYPE_SDRAM 0 #define SYSCFG0_DRAM_TYPE_DDR1 1 #define SYSCFG0_DRAM_TYPE_DDR2 2 +#define SYSCFG0_DRAM_TYPE_UNKNOWN 3 #define SYSCFG0_DRAM_TYPE_DDR2_MT7628 0 #define SYSCFG0_DRAM_TYPE_DDR1_MT7628 1 diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 2c623f6bca08..88b82fe21ae6 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -581,11 +581,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info) (rev & CHIP_REV_ECO_MASK)); cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); - if (is_mt76x8()) + if (is_mt76x8()) { dram_type = cfg0 & DRAM_TYPE_MT7628_MASK; - else + } else { dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN) + dram_type = SYSCFG0_DRAM_TYPE_SDRAM; + } soc_info->mem_base = MT7620_DRAM_BASE; if (is_mt76x8()) -- cgit v1.2.3-59-g8ed1b From 80fa40acaa1dad5a0a9c15ed2e5d2e72461843f5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 19 Apr 2016 15:35:39 -0700 Subject: MIPS: BMIPS: Adjust mips-hpt-frequency for BCM7435 The CPU actually runs at 1405Mhz which gives us a 175625000 Hz MIPS timer frequency (CPU frequency / 8). Fixes: e4c7d009654a ("MIPS: BMIPS: Add BCM7435 dtsi") Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jaedon.shin@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/13132/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7435.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index cce752b27055..a874d3a0e2ee 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -7,7 +7,7 @@ #address-cells = <1>; #size-cells = <0>; - mips-hpt-frequency = <163125000>; + mips-hpt-frequency = <175625000>; cpu@0 { compatible = "brcm,bmips5200"; -- cgit v1.2.3-59-g8ed1b From ae07ea85bd2900d0df0c17724b252131ddae4b50 Mon Sep 17 00:00:00 2001 From: James Hartley Date: Tue, 19 Apr 2016 15:46:55 +0100 Subject: MIPS: pistachio: Determine SoC revision during boot Now that there are different revisions of the Pistachio SoC in circulation, add this information to the boot log to make it easier for users to determine which hardware they have. Signed-off-by: James Hartley Signed-off-by: Ionela Voinescu Cc: Andrew Bresticker Cc: Jonas Gorski Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13130/ Signed-off-by: Ralf Baechle --- arch/mips/pistachio/init.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c index 96ba2cc9ad3e..956c92eabfab 100644 --- a/arch/mips/pistachio/init.c +++ b/arch/mips/pistachio/init.c @@ -2,6 +2,7 @@ * Pistachio platform setup * * Copyright (C) 2014 Google, Inc. + * Copyright (C) 2016 Imagination 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, @@ -9,6 +10,7 @@ */ #include +#include #include #include #include @@ -24,9 +26,38 @@ #include #include +/* + * Core revision register decoding + * Bits 23 to 20: Major rev + * Bits 15 to 8: Minor rev + * Bits 7 to 0: Maintenance rev + */ +#define PISTACHIO_CORE_REV_REG 0xB81483D0 +#define PISTACHIO_CORE_REV_A1 0x00100006 +#define PISTACHIO_CORE_REV_B0 0x00100106 + const char *get_system_type(void) { - return "IMG Pistachio SoC"; + u32 core_rev; + const char *sys_type; + + core_rev = __raw_readl((const void *)PISTACHIO_CORE_REV_REG); + + switch (core_rev) { + case PISTACHIO_CORE_REV_B0: + sys_type = "IMG Pistachio SoC (B0)"; + break; + + case PISTACHIO_CORE_REV_A1: + sys_type = "IMG Pistachio SoC (A1)"; + break; + + default: + sys_type = "IMG Pistachio SoC"; + break; + } + + return sys_type; } static void __init plat_setup_iocoherency(void) @@ -109,6 +140,8 @@ void __init prom_init(void) mips_cm_probe(); mips_cpc_probe(); register_cps_smp_ops(); + + pr_info("SoC Type: %s\n", get_system_type()); } void __init prom_free_prom_memory(void) -- cgit v1.2.3-59-g8ed1b From 46d6ccdbf384f3659e204824d3bce40c1fa989de Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Mon, 18 Apr 2016 20:58:51 +0200 Subject: MIPS: JZ4740: Qi LB60: Remove support for AVT2 variant AVT2 was a prototype board of which about 5 were made, none of which are in use anymore. Signed-off-by: Maarten ter Huurne Acked-by: Lars-Peter Clausen Cc: Paul Cercueil Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13103/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/board-qi_lb60.c | 52 ++-------------------------------------- 1 file changed, 2 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 934b15b5b575..4e3f9b7a02e4 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -39,8 +39,6 @@ #include "clock.h" -static bool is_avt2; - /* GPIOs */ #define QI_LB60_GPIO_SD_CD JZ_GPIO_PORTD(0) #define QI_LB60_GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(2) @@ -367,43 +365,12 @@ static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = { .power_active_low = 1, }; -/* OHCI */ -static struct regulator_consumer_supply avt2_usb_regulator_consumer = - REGULATOR_SUPPLY("vbus", "jz4740-ohci"); - -static struct regulator_init_data avt2_usb_regulator_init_data = { - .num_consumer_supplies = 1, - .consumer_supplies = &avt2_usb_regulator_consumer, - .constraints = { - .name = "USB power", - .min_uV = 5000000, - .max_uV = 5000000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, -}; - -static struct fixed_voltage_config avt2_usb_regulator_data = { - .supply_name = "USB power", - .microvolts = 5000000, - .gpio = JZ_GPIO_PORTB(17), - .init_data = &avt2_usb_regulator_init_data, -}; - -static struct platform_device avt2_usb_regulator_device = { - .name = "reg-fixed-voltage", - .id = -1, - .dev = { - .platform_data = &avt2_usb_regulator_data, - } -}; - +/* beeper */ static struct pwm_lookup qi_lb60_pwm_lookup[] = { PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0, PWM_POLARITY_NORMAL), }; -/* beeper */ static struct platform_device qi_lb60_pwm_beeper = { .name = "pwm-beeper", .id = -1, @@ -487,11 +454,6 @@ static int __init qi_lb60_init_platform_devices(void) spi_register_board_info(qi_lb60_spi_board_info, ARRAY_SIZE(qi_lb60_spi_board_info)); - if (is_avt2) { - platform_device_register(&avt2_usb_regulator_device); - platform_device_register(&jz4740_usb_ohci_device); - } - pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup)); return platform_add_devices(jz_platform_devices, @@ -499,19 +461,9 @@ static int __init qi_lb60_init_platform_devices(void) } -static __init int board_avt2(char *str) -{ - qi_lb60_mmc_pdata.card_detect_active_low = 1; - is_avt2 = true; - - return 1; -} -__setup("avt2", board_avt2); - static int __init qi_lb60_board_setup(void) { - printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n", - is_avt2 ? "AVT2" : "LB60"); + printk(KERN_INFO "Qi Hardware JZ4740 QI LB60 setup\n"); board_gpio_setup(); -- cgit v1.2.3-59-g8ed1b From 9d1e7875fafc45dbcbe3d816b022aa1f17219f32 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Mon, 18 Apr 2016 20:58:52 +0200 Subject: MIPS: JZ4740: Probe OHCI platform device via DT The DT fragment will select the ohci-platform driver, since that can handle the JZ4740 OHCI just fine. While I don't have a JZ4740-based board with anything connected to the USB host controller, I did test the generic OHCI driver successfully on a JZ4770-based board. The device is disabled by default; boards that want to use it can override the "status" property. The mass-production Qi LB60 boards don't use the USB host controller. Signed-off-by: Maarten ter Huurne Cc: Lars-Peter Clausen Cc: Paul Cercueil Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13104/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/ingenic/jz4740.dtsi | 14 ++++++++++++++ arch/mips/include/asm/mach-jz4740/platform.h | 1 - arch/mips/jz4740/platform.c | 25 ------------------------- 3 files changed, 14 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 8b2437cd019f..4a9c8f2a72d6 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -65,4 +65,18 @@ clocks = <&ext>, <&cgu JZ4740_CLK_UART1>; clock-names = "baud", "module"; }; + + uhc: uhc@13030000 { + compatible = "ingenic,jz4740-ohci", "generic-ohci"; + reg = <0x13030000 0x1000>; + + clocks = <&cgu JZ4740_CLK_UHC>; + assigned-clocks = <&cgu JZ4740_CLK_UHC>; + assigned-clock-rates = <48000000>; + + interrupt-parent = <&intc>; + interrupts = <3>; + + status = "disabled"; + }; }; diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 32cfbe6a191b..073b8bfbb3b3 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -19,7 +19,6 @@ #include -extern struct platform_device jz4740_usb_ohci_device; extern struct platform_device jz4740_udc_device; extern struct platform_device jz4740_udc_xceiv_device; extern struct platform_device jz4740_mmc_device; diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index e8a463b9b663..2f1dab35c061 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -32,31 +32,6 @@ #include "clock.h" -/* OHCI controller */ -static struct resource jz4740_usb_ohci_resources[] = { - { - .start = JZ4740_UHC_BASE_ADDR, - .end = JZ4740_UHC_BASE_ADDR + 0x1000 - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = JZ4740_IRQ_UHC, - .end = JZ4740_IRQ_UHC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device jz4740_usb_ohci_device = { - .name = "jz4740-ohci", - .id = -1, - .dev = { - .dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources), - .resource = jz4740_usb_ohci_resources, -}; - /* USB Device Controller */ struct platform_device jz4740_udc_xceiv_device = { .name = "usb_phy_generic", -- cgit v1.2.3-59-g8ed1b From 2afb97454347f641dd2435a3956ba12f816fb1df Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 13 May 2016 19:41:06 +0100 Subject: MIPS: Fix genvdso error on rebuild The genvdso program modifies the debug and stripped versions of the VDSOs in place, and errors if the modification has already taken place. Unfortunately this means that a rebuild which tries to rerun genvdso to generate vdso*-image.c without also rebuilding vdso.so.dbg (for example if genvdso.c is modified) hits a build error like this: arch/mips/vdso/genvdso 'arch/mips/vdso/vdso.so.dbg' already contains a '.MIPS.abiflags' section This is fixed by reorganising the rules such that unmodified .so files have a .raw suffix, and these are copied in the same rule that runs genvdso on the copies. I.e. previously we had: cmd_vdsold: link objects -> vdso.so.dbg cmd_genvdso: strip vdso.so.dbg -> vdso.so run genvdso -> vdso-image.c and modify vdso.so.dbg and vdso.so in place Now we have: cmd_vdsold: link objects -> vdso.so.dbg.raw a new cmd_objcopy based strip rule (inspired by ARM): strip vdso.so.dbg.raw -> vdso.so.raw cmd_genvdso: copy vdso.so.dbg.raw -> vdso.so.dbg copy vdso.so.raw -> vdso.so run genvdso -> vdso-image.c and modify vdso.so.dbg and vdso.so in place Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13250/ Signed-off-by: Ralf Baechle --- arch/mips/vdso/Makefile | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile index ee3617c0c5e2..b369509e9753 100644 --- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile @@ -50,13 +50,17 @@ quiet_cmd_vdsold = VDSO $@ cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \ -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@ +# Strip rule for the raw .so files +$(obj)/%.so.raw: OBJCOPYFLAGS := -S +$(obj)/%.so.raw: $(obj)/%.so.dbg.raw FORCE + $(call if_changed,objcopy) + hostprogs-y := genvdso quiet_cmd_genvdso = GENVDSO $@ define cmd_genvdso - cp $< $(<:%.dbg=%) && \ - $(OBJCOPY) -S $< $(<:%.dbg=%) && \ - $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME) + $(foreach file,$(filter %.raw,$^),cp $(file) $(file:%.raw=%) &&) \ + $(obj)/genvdso $(<:%.raw=%) $(<:%.dbg.raw=%) $@ $(VDSO_NAME) endef # @@ -66,7 +70,10 @@ endef native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS)) targets += $(obj-vdso-y) -targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c +targets += vdso.lds +targets += vdso.so.dbg.raw vdso.so.raw +targets += vdso.so.dbg vdso.so +targets += vdso-image.c obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o) @@ -75,10 +82,11 @@ $(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi) $(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi) -$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE +$(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE $(call if_changed,vdsold) -$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE +$(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \ + $(obj)/genvdso FORCE $(call if_changed,genvdso) obj-y += vdso-image.o @@ -89,7 +97,10 @@ obj-y += vdso-image.o # Define these outside the ifdef to ensure they are picked up by clean. targets += $(obj-vdso-y:%.o=%-o32.o) -targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c +targets += vdso-o32.lds +targets += vdso-o32.so.dbg.raw vdso-o32.so.raw +targets += vdso-o32.so.dbg vdso-o32.so +targets += vdso-o32-image.c ifdef CONFIG_MIPS32_O32 @@ -109,11 +120,12 @@ $(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE $(call if_changed_dep,cpp_lds_S) -$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE +$(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE $(call if_changed,vdsold) $(obj)/vdso-o32-image.c: VDSO_NAME := o32 -$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE +$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \ + $(obj)/genvdso FORCE $(call if_changed,genvdso) obj-y += vdso-o32-image.o @@ -125,7 +137,10 @@ endif # targets += $(obj-vdso-y:%.o=%-n32.o) -targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c +targets += vdso-n32.lds +targets += vdso-n32.so.dbg.raw vdso-n32.so.raw +targets += vdso-n32.so.dbg vdso-n32.so +targets += vdso-n32-image.c ifdef CONFIG_MIPS32_N32 @@ -145,11 +160,12 @@ $(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE $(call if_changed_dep,cpp_lds_S) -$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE +$(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE $(call if_changed,vdsold) $(obj)/vdso-n32-image.c: VDSO_NAME := n32 -$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE +$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \ + $(obj)/genvdso FORCE $(call if_changed,genvdso) obj-y += vdso-n32-image.o -- cgit v1.2.3-59-g8ed1b From 0868971a8dad52e726711a2a4b161ace9ed011fa Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 4 Dec 2015 19:40:00 +0800 Subject: MIPS: CM: Fix compilation error when !MIPS_CM Fix mips_cm_lock_other compilation error when MIPS_CM is not selected. This was introduced in commit 23d5de8efb9a (MIPS: CM: Introduce core-other locking functions) Signed-off-by: Tony Wu Cc: Paul Burton Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11698/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 3fea29e50c46..9411a4c0bdad 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -509,7 +509,7 @@ extern void mips_cm_unlock_other(void); #else /* !CONFIG_MIPS_CM */ -static inline void mips_cm_lock_other(unsigned int core) { } +static inline void mips_cm_lock_other(unsigned int core, unsigned int vp) { } static inline void mips_cm_unlock_other(void) { } #endif /* !CONFIG_MIPS_CM */ -- cgit v1.2.3-59-g8ed1b From e49d38488515057dba8f0c2ba4cfde5be4a7281f Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 17 May 2016 06:12:27 +0100 Subject: MIPS: MSA: Fix a link error on `_init_msa_upper' with older GCC Fix a build regression from commit c9017757c532 ("MIPS: init upper 64b of vector registers when MSA is first used"): arch/mips/built-in.o: In function `enable_restore_fp_context': traps.c:(.text+0xbb90): undefined reference to `_init_msa_upper' traps.c:(.text+0xbb90): relocation truncated to fit: R_MIPS_26 against `_init_msa_upper' traps.c:(.text+0xbef0): undefined reference to `_init_msa_upper' traps.c:(.text+0xbef0): relocation truncated to fit: R_MIPS_26 against `_init_msa_upper' to !CONFIG_CPU_HAS_MSA configurations with older GCC versions, which are unable to figure out that calls to `_init_msa_upper' are indeed dead. Of the many ways to tackle this failure choose the approach we have already taken in `thread_msa_context_live'. [ralf@linux-mips.org: Drop patch segment to junk file.] Signed-off-by: Maciej W. Rozycki Cc: stable@vger.kernel.org # v3.16+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13271/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/msa.h | 13 +++++++++++++ arch/mips/kernel/traps.c | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h index bbb85fe21642..6e4effa6f626 100644 --- a/arch/mips/include/asm/msa.h +++ b/arch/mips/include/asm/msa.h @@ -147,6 +147,19 @@ static inline void restore_msa(struct task_struct *t) _restore_msa(t); } +static inline void init_msa_upper(void) +{ + /* + * Check cpu_has_msa only if it's a constant. This will allow the + * compiler to optimise out code for CPUs without MSA without adding + * an extra redundant check for CPUs with MSA. + */ + if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa) + return; + + _init_msa_upper(); +} + #ifdef TOOLCHAIN_SUPPORTS_MSA #define __BUILD_MSA_CTL_REG(name, cs) \ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 56f4161b98b9..4a1712b5abdf 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1246,7 +1246,7 @@ static int enable_restore_fp_context(int msa) err = init_fpu(); if (msa && !err) { enable_msa(); - _init_msa_upper(); + init_msa_upper(); set_thread_flag(TIF_USEDMSA); set_thread_flag(TIF_MSA_CTX_LIVE); } @@ -1309,7 +1309,7 @@ static int enable_restore_fp_context(int msa) */ prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE); if (!prior_msa && was_fpu_owner) { - _init_msa_upper(); + init_msa_upper(); goto out; } @@ -1326,7 +1326,7 @@ static int enable_restore_fp_context(int msa) * of each vector register such that it cannot see data left * behind by another task. */ - _init_msa_upper(); + init_msa_upper(); } else { /* We need to restore the vector context. */ restore_msa(current); -- cgit v1.2.3-59-g8ed1b From e48b4dacbc94fcb59b86f70f01837ed75ea6d616 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 16 May 2016 13:15:47 +0100 Subject: MIPS: DEC: Export `ioasic_ssr_lock' to modules Fix a modular `declance' regression caused by LMO commit bb46bf30d13f ("DECstation SCSI driver clean-ups.") Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13256/ Signed-off-by: Ralf Baechle --- arch/mips/dec/setup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index a0b8943c8f11..1c3bf9fe926f 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -60,6 +60,7 @@ EXPORT_SYMBOL(dec_kn_slot_size); int dec_tc_bus; DEFINE_SPINLOCK(ioasic_ssr_lock); +EXPORT_SYMBOL(ioasic_ssr_lock); volatile u32 *ioasic_base; -- cgit v1.2.3-59-g8ed1b From fd716fca10fc3dc0f18b8c16d4ecfa6d93f010d2 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 16 May 2016 19:32:35 +0100 Subject: MIPS: perf: Fix I6400 event numbers Fix perf hardware performance counter event numbers for I6400. This core does not follow the performance event numbering scheme of previous MIPS cores. All performance counters (both odd and even) are capable of counting any of the available events. Fixes: 4e88a8621301 ("MIPS: Add cases for CPU_I6400") Signed-off-by: James Hogan Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13259/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/perf_event_mipsxx.c | 54 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 302af8c975df..d3ba9f4105b5 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -823,6 +823,16 @@ static const struct mips_perf_event mipsxxcore_event_map2 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T }, }; +static const struct mips_perf_event i6400_event_map[PERF_COUNT_HW_MAX] = { + [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD }, + /* These only count dcache, not icache */ + [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x45, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_CACHE_MISSES] = { 0x48, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x15, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_BRANCH_MISSES] = { 0x16, CNTR_EVEN | CNTR_ODD }, +}; + static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN }, [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD }, @@ -1013,6 +1023,46 @@ static const struct mips_perf_event mipsxxcore_cache_map2 }, }; +static const struct mips_perf_event i6400_cache_map + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +[C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x46, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x49, CNTR_EVEN | CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x47, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x4a, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x84, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x85, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(DTLB)] = { + /* Can't distinguish read & write */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x40, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x41, CNTR_EVEN | CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x40, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x41, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(BPU)] = { + /* Conditional branches / mispredicted */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x15, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x16, CNTR_EVEN | CNTR_ODD }, + }, +}, +}; + static const struct mips_perf_event loongson3_cache_map [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] @@ -1724,8 +1774,8 @@ init_hw_perf_events(void) break; case CPU_I6400: mipspmu.name = "mips/I6400"; - mipspmu.general_event_map = &mipsxxcore_event_map2; - mipspmu.cache_event_map = &mipsxxcore_cache_map2; + mipspmu.general_event_map = &i6400_event_map; + mipspmu.cache_event_map = &i6400_cache_map; break; case CPU_1004K: mipspmu.name = "mips/1004K"; -- cgit v1.2.3-59-g8ed1b From bad50d79255a8a479ea63bea89e859bf08fd0f24 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 16 May 2016 12:50:04 +0100 Subject: MIPS: Fix VZ probe gas errors with binutils <2.24 The VZ guest register & TLB access macros introduced in commit "MIPS: Add guest CP0 accessors" use VZ ASE specific instructions that aren't understood by versions of binutils prior to 2.24. Add a check for whether the toolchain supports the -mvirt option, similar to the MSA toolchain check, and implement the accessors using .word if not. Due to difficulty in converting compiler specified registers (e.g. "$3") to usable numbers (e.g. "3") in inline asm, we need to copy to/from a temporary register, namely the assembler temporary (at/$1), and specify guest CP0 registers numerically in the gc0 macros. Fixes: 7eb91118227d ("MIPS: Add guest CP0 accessors") Signed-off-by: James Hogan Reported-by: Guenter Roeck Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: linux-next@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13255/ Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 2 + arch/mips/include/asm/mipsregs.h | 473 ++++++++++++++++++++++++--------------- 2 files changed, 295 insertions(+), 180 deletions(-) (limited to 'arch') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index c0b002a09bef..efd7a9dc93c4 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -200,6 +200,8 @@ ifeq ($(CONFIG_CPU_HAS_MSA),y) toolchain-msa := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(comma)-mmsa) cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA endif +toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt) +cflags-$(toolchain-virt) += -DTOOLCHAIN_SUPPORTS_VIRT cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER) += -mcompact-branches=never cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 1019de6bb2a8..25d01577d0b5 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1683,15 +1683,18 @@ do { \ * Macros to access the guest system control coprocessor */ +#ifdef TOOLCHAIN_SUPPORTS_VIRT + #define __read_32bit_gc0_register(source, sel) \ ({ int __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ ".set\tmips32r2\n\t" \ ".set\tvirt\n\t" \ - "mfgc0\t%0, " #source ", " #sel "\n\t" \ + "mfgc0\t%0, $%1, %2\n\t" \ ".set\tpop" \ - : "=r" (__res)); \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ __res; \ }) @@ -1701,9 +1704,10 @@ do { \ ".set\tpush\n\t" \ ".set\tmips64r2\n\t" \ ".set\tvirt\n\t" \ - "dmfgc0\t%0, " #source ", " #sel "\n\t" \ + "dmfgc0\t%0, $%1, %2\n\t" \ ".set\tpop" \ - : "=r" (__res)); \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ __res; \ }) @@ -1713,9 +1717,10 @@ do { \ ".set\tpush\n\t" \ ".set\tmips32r2\n\t" \ ".set\tvirt\n\t" \ - "mtgc0\t%z0, " #register ", " #sel "\n\t" \ + "mtgc0\t%z0, $%1, %2\n\t" \ ".set\tpop" \ - : : "Jr" ((unsigned int)(value))); \ + : : "Jr" ((unsigned int)(value)), \ + "i" (register), "i" (sel)); \ } while (0) #define __write_64bit_gc0_register(register, sel, value) \ @@ -1724,11 +1729,70 @@ do { \ ".set\tpush\n\t" \ ".set\tmips64r2\n\t" \ ".set\tvirt\n\t" \ - "dmtgc0\t%z0, " #register ", " #sel "\n\t" \ + "dmtgc0\t%z0, $%1, %2\n\t" \ + ".set\tpop" \ + : : "Jr" (value), \ + "i" (register), "i" (sel)); \ +} while (0) + +#else /* TOOLCHAIN_SUPPORTS_VIRT */ + +#define __read_32bit_gc0_register(source, sel) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "# mfgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610000 | %1 << 11 | %2)\n\t" \ + "move\t%0, $1\n\t" \ + ".set\tpop" \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ + __res; \ +}) + +#define __read_64bit_gc0_register(source, sel) \ +({ unsigned long long __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "# dmfgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610100 | %1 << 11 | %2)\n\t" \ + "move\t%0, $1\n\t" \ + ".set\tpop" \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ + __res; \ +}) + +#define __write_32bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "move\t$1, %0\n\t" \ + "# mtgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610200 | %1 << 11 | %2)\n\t" \ ".set\tpop" \ - : : "Jr" (value)); \ + : : "Jr" ((unsigned int)(value)), \ + "i" (register), "i" (sel)); \ } while (0) +#define __write_64bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "move\t$1, %0\n\t" \ + "# dmtgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610300 | %1 << 11 | %2)\n\t" \ + ".set\tpop" \ + : : "Jr" (value), \ + "i" (register), "i" (sel)); \ +} while (0) + +#endif /* !TOOLCHAIN_SUPPORTS_VIRT */ + #define __read_ulong_gc0_register(reg, sel) \ ((sizeof(unsigned long) == 4) ? \ (unsigned long) __read_32bit_gc0_register(reg, sel) : \ @@ -1742,189 +1806,189 @@ do { \ __write_64bit_gc0_register(reg, sel, val); \ } while (0) -#define read_gc0_index() __read_32bit_gc0_register($0, 0) -#define write_gc0_index(val) __write_32bit_gc0_register($0, 0, val) +#define read_gc0_index() __read_32bit_gc0_register(0, 0) +#define write_gc0_index(val) __write_32bit_gc0_register(0, 0, val) -#define read_gc0_entrylo0() __read_ulong_gc0_register($2, 0) -#define write_gc0_entrylo0(val) __write_ulong_gc0_register($2, 0, val) +#define read_gc0_entrylo0() __read_ulong_gc0_register(2, 0) +#define write_gc0_entrylo0(val) __write_ulong_gc0_register(2, 0, val) -#define read_gc0_entrylo1() __read_ulong_gc0_register($3, 0) -#define write_gc0_entrylo1(val) __write_ulong_gc0_register($3, 0, val) +#define read_gc0_entrylo1() __read_ulong_gc0_register(3, 0) +#define write_gc0_entrylo1(val) __write_ulong_gc0_register(3, 0, val) -#define read_gc0_context() __read_ulong_gc0_register($4, 0) -#define write_gc0_context(val) __write_ulong_gc0_register($4, 0, val) +#define read_gc0_context() __read_ulong_gc0_register(4, 0) +#define write_gc0_context(val) __write_ulong_gc0_register(4, 0, val) -#define read_gc0_contextconfig() __read_32bit_gc0_register($4, 1) -#define write_gc0_contextconfig(val) __write_32bit_gc0_register($4, 1, val) +#define read_gc0_contextconfig() __read_32bit_gc0_register(4, 1) +#define write_gc0_contextconfig(val) __write_32bit_gc0_register(4, 1, val) -#define read_gc0_userlocal() __read_ulong_gc0_register($4, 2) -#define write_gc0_userlocal(val) __write_ulong_gc0_register($4, 2, val) +#define read_gc0_userlocal() __read_ulong_gc0_register(4, 2) +#define write_gc0_userlocal(val) __write_ulong_gc0_register(4, 2, val) -#define read_gc0_xcontextconfig() __read_ulong_gc0_register($4, 3) -#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register($4, 3, val) +#define read_gc0_xcontextconfig() __read_ulong_gc0_register(4, 3) +#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register(4, 3, val) -#define read_gc0_pagemask() __read_32bit_gc0_register($5, 0) -#define write_gc0_pagemask(val) __write_32bit_gc0_register($5, 0, val) +#define read_gc0_pagemask() __read_32bit_gc0_register(5, 0) +#define write_gc0_pagemask(val) __write_32bit_gc0_register(5, 0, val) -#define read_gc0_pagegrain() __read_32bit_gc0_register($5, 1) -#define write_gc0_pagegrain(val) __write_32bit_gc0_register($5, 1, val) +#define read_gc0_pagegrain() __read_32bit_gc0_register(5, 1) +#define write_gc0_pagegrain(val) __write_32bit_gc0_register(5, 1, val) -#define read_gc0_segctl0() __read_ulong_gc0_register($5, 2) -#define write_gc0_segctl0(val) __write_ulong_gc0_register($5, 2, val) +#define read_gc0_segctl0() __read_ulong_gc0_register(5, 2) +#define write_gc0_segctl0(val) __write_ulong_gc0_register(5, 2, val) -#define read_gc0_segctl1() __read_ulong_gc0_register($5, 3) -#define write_gc0_segctl1(val) __write_ulong_gc0_register($5, 3, val) +#define read_gc0_segctl1() __read_ulong_gc0_register(5, 3) +#define write_gc0_segctl1(val) __write_ulong_gc0_register(5, 3, val) -#define read_gc0_segctl2() __read_ulong_gc0_register($5, 4) -#define write_gc0_segctl2(val) __write_ulong_gc0_register($5, 4, val) - -#define read_gc0_pwbase() __read_ulong_gc0_register($5, 5) -#define write_gc0_pwbase(val) __write_ulong_gc0_register($5, 5, val) - -#define read_gc0_pwfield() __read_ulong_gc0_register($5, 6) -#define write_gc0_pwfield(val) __write_ulong_gc0_register($5, 6, val) - -#define read_gc0_pwsize() __read_ulong_gc0_register($5, 7) -#define write_gc0_pwsize(val) __write_ulong_gc0_register($5, 7, val) - -#define read_gc0_wired() __read_32bit_gc0_register($6, 0) -#define write_gc0_wired(val) __write_32bit_gc0_register($6, 0, val) - -#define read_gc0_pwctl() __read_32bit_gc0_register($6, 6) -#define write_gc0_pwctl(val) __write_32bit_gc0_register($6, 6, val) - -#define read_gc0_hwrena() __read_32bit_gc0_register($7, 0) -#define write_gc0_hwrena(val) __write_32bit_gc0_register($7, 0, val) - -#define read_gc0_badvaddr() __read_ulong_gc0_register($8, 0) -#define write_gc0_badvaddr(val) __write_ulong_gc0_register($8, 0, val) - -#define read_gc0_badinstr() __read_32bit_gc0_register($8, 1) -#define write_gc0_badinstr(val) __write_32bit_gc0_register($8, 1, val) - -#define read_gc0_badinstrp() __read_32bit_gc0_register($8, 2) -#define write_gc0_badinstrp(val) __write_32bit_gc0_register($8, 2, val) - -#define read_gc0_count() __read_32bit_gc0_register($9, 0) - -#define read_gc0_entryhi() __read_ulong_gc0_register($10, 0) -#define write_gc0_entryhi(val) __write_ulong_gc0_register($10, 0, val) - -#define read_gc0_compare() __read_32bit_gc0_register($11, 0) -#define write_gc0_compare(val) __write_32bit_gc0_register($11, 0, val) - -#define read_gc0_status() __read_32bit_gc0_register($12, 0) -#define write_gc0_status(val) __write_32bit_gc0_register($12, 0, val) - -#define read_gc0_intctl() __read_32bit_gc0_register($12, 1) -#define write_gc0_intctl(val) __write_32bit_gc0_register($12, 1, val) - -#define read_gc0_cause() __read_32bit_gc0_register($13, 0) -#define write_gc0_cause(val) __write_32bit_gc0_register($13, 0, val) - -#define read_gc0_epc() __read_ulong_gc0_register($14, 0) -#define write_gc0_epc(val) __write_ulong_gc0_register($14, 0, val) - -#define read_gc0_ebase() __read_32bit_gc0_register($15, 1) -#define write_gc0_ebase(val) __write_32bit_gc0_register($15, 1, val) - -#define read_gc0_ebase_64() __read_64bit_gc0_register($15, 1) -#define write_gc0_ebase_64(val) __write_64bit_gc0_register($15, 1, val) - -#define read_gc0_config() __read_32bit_gc0_register($16, 0) -#define read_gc0_config1() __read_32bit_gc0_register($16, 1) -#define read_gc0_config2() __read_32bit_gc0_register($16, 2) -#define read_gc0_config3() __read_32bit_gc0_register($16, 3) -#define read_gc0_config4() __read_32bit_gc0_register($16, 4) -#define read_gc0_config5() __read_32bit_gc0_register($16, 5) -#define read_gc0_config6() __read_32bit_gc0_register($16, 6) -#define read_gc0_config7() __read_32bit_gc0_register($16, 7) -#define write_gc0_config(val) __write_32bit_gc0_register($16, 0, val) -#define write_gc0_config1(val) __write_32bit_gc0_register($16, 1, val) -#define write_gc0_config2(val) __write_32bit_gc0_register($16, 2, val) -#define write_gc0_config3(val) __write_32bit_gc0_register($16, 3, val) -#define write_gc0_config4(val) __write_32bit_gc0_register($16, 4, val) -#define write_gc0_config5(val) __write_32bit_gc0_register($16, 5, val) -#define write_gc0_config6(val) __write_32bit_gc0_register($16, 6, val) -#define write_gc0_config7(val) __write_32bit_gc0_register($16, 7, val) - -#define read_gc0_watchlo0() __read_ulong_gc0_register($18, 0) -#define read_gc0_watchlo1() __read_ulong_gc0_register($18, 1) -#define read_gc0_watchlo2() __read_ulong_gc0_register($18, 2) -#define read_gc0_watchlo3() __read_ulong_gc0_register($18, 3) -#define read_gc0_watchlo4() __read_ulong_gc0_register($18, 4) -#define read_gc0_watchlo5() __read_ulong_gc0_register($18, 5) -#define read_gc0_watchlo6() __read_ulong_gc0_register($18, 6) -#define read_gc0_watchlo7() __read_ulong_gc0_register($18, 7) -#define write_gc0_watchlo0(val) __write_ulong_gc0_register($18, 0, val) -#define write_gc0_watchlo1(val) __write_ulong_gc0_register($18, 1, val) -#define write_gc0_watchlo2(val) __write_ulong_gc0_register($18, 2, val) -#define write_gc0_watchlo3(val) __write_ulong_gc0_register($18, 3, val) -#define write_gc0_watchlo4(val) __write_ulong_gc0_register($18, 4, val) -#define write_gc0_watchlo5(val) __write_ulong_gc0_register($18, 5, val) -#define write_gc0_watchlo6(val) __write_ulong_gc0_register($18, 6, val) -#define write_gc0_watchlo7(val) __write_ulong_gc0_register($18, 7, val) - -#define read_gc0_watchhi0() __read_32bit_gc0_register($19, 0) -#define read_gc0_watchhi1() __read_32bit_gc0_register($19, 1) -#define read_gc0_watchhi2() __read_32bit_gc0_register($19, 2) -#define read_gc0_watchhi3() __read_32bit_gc0_register($19, 3) -#define read_gc0_watchhi4() __read_32bit_gc0_register($19, 4) -#define read_gc0_watchhi5() __read_32bit_gc0_register($19, 5) -#define read_gc0_watchhi6() __read_32bit_gc0_register($19, 6) -#define read_gc0_watchhi7() __read_32bit_gc0_register($19, 7) -#define write_gc0_watchhi0(val) __write_32bit_gc0_register($19, 0, val) -#define write_gc0_watchhi1(val) __write_32bit_gc0_register($19, 1, val) -#define write_gc0_watchhi2(val) __write_32bit_gc0_register($19, 2, val) -#define write_gc0_watchhi3(val) __write_32bit_gc0_register($19, 3, val) -#define write_gc0_watchhi4(val) __write_32bit_gc0_register($19, 4, val) -#define write_gc0_watchhi5(val) __write_32bit_gc0_register($19, 5, val) -#define write_gc0_watchhi6(val) __write_32bit_gc0_register($19, 6, val) -#define write_gc0_watchhi7(val) __write_32bit_gc0_register($19, 7, val) - -#define read_gc0_xcontext() __read_ulong_gc0_register($20, 0) -#define write_gc0_xcontext(val) __write_ulong_gc0_register($20, 0, val) - -#define read_gc0_perfctrl0() __read_32bit_gc0_register($25, 0) -#define write_gc0_perfctrl0(val) __write_32bit_gc0_register($25, 0, val) -#define read_gc0_perfcntr0() __read_32bit_gc0_register($25, 1) -#define write_gc0_perfcntr0(val) __write_32bit_gc0_register($25, 1, val) -#define read_gc0_perfcntr0_64() __read_64bit_gc0_register($25, 1) -#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register($25, 1, val) -#define read_gc0_perfctrl1() __read_32bit_gc0_register($25, 2) -#define write_gc0_perfctrl1(val) __write_32bit_gc0_register($25, 2, val) -#define read_gc0_perfcntr1() __read_32bit_gc0_register($25, 3) -#define write_gc0_perfcntr1(val) __write_32bit_gc0_register($25, 3, val) -#define read_gc0_perfcntr1_64() __read_64bit_gc0_register($25, 3) -#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register($25, 3, val) -#define read_gc0_perfctrl2() __read_32bit_gc0_register($25, 4) -#define write_gc0_perfctrl2(val) __write_32bit_gc0_register($25, 4, val) -#define read_gc0_perfcntr2() __read_32bit_gc0_register($25, 5) -#define write_gc0_perfcntr2(val) __write_32bit_gc0_register($25, 5, val) -#define read_gc0_perfcntr2_64() __read_64bit_gc0_register($25, 5) -#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register($25, 5, val) -#define read_gc0_perfctrl3() __read_32bit_gc0_register($25, 6) -#define write_gc0_perfctrl3(val) __write_32bit_gc0_register($25, 6, val) -#define read_gc0_perfcntr3() __read_32bit_gc0_register($25, 7) -#define write_gc0_perfcntr3(val) __write_32bit_gc0_register($25, 7, val) -#define read_gc0_perfcntr3_64() __read_64bit_gc0_register($25, 7) -#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register($25, 7, val) - -#define read_gc0_errorepc() __read_ulong_gc0_register($30, 0) -#define write_gc0_errorepc(val) __write_ulong_gc0_register($30, 0, val) - -#define read_gc0_kscratch1() __read_ulong_gc0_register($31, 2) -#define read_gc0_kscratch2() __read_ulong_gc0_register($31, 3) -#define read_gc0_kscratch3() __read_ulong_gc0_register($31, 4) -#define read_gc0_kscratch4() __read_ulong_gc0_register($31, 5) -#define read_gc0_kscratch5() __read_ulong_gc0_register($31, 6) -#define read_gc0_kscratch6() __read_ulong_gc0_register($31, 7) -#define write_gc0_kscratch1(val) __write_ulong_gc0_register($31, 2, val) -#define write_gc0_kscratch2(val) __write_ulong_gc0_register($31, 3, val) -#define write_gc0_kscratch3(val) __write_ulong_gc0_register($31, 4, val) -#define write_gc0_kscratch4(val) __write_ulong_gc0_register($31, 5, val) -#define write_gc0_kscratch5(val) __write_ulong_gc0_register($31, 6, val) -#define write_gc0_kscratch6(val) __write_ulong_gc0_register($31, 7, val) +#define read_gc0_segctl2() __read_ulong_gc0_register(5, 4) +#define write_gc0_segctl2(val) __write_ulong_gc0_register(5, 4, val) + +#define read_gc0_pwbase() __read_ulong_gc0_register(5, 5) +#define write_gc0_pwbase(val) __write_ulong_gc0_register(5, 5, val) + +#define read_gc0_pwfield() __read_ulong_gc0_register(5, 6) +#define write_gc0_pwfield(val) __write_ulong_gc0_register(5, 6, val) + +#define read_gc0_pwsize() __read_ulong_gc0_register(5, 7) +#define write_gc0_pwsize(val) __write_ulong_gc0_register(5, 7, val) + +#define read_gc0_wired() __read_32bit_gc0_register(6, 0) +#define write_gc0_wired(val) __write_32bit_gc0_register(6, 0, val) + +#define read_gc0_pwctl() __read_32bit_gc0_register(6, 6) +#define write_gc0_pwctl(val) __write_32bit_gc0_register(6, 6, val) + +#define read_gc0_hwrena() __read_32bit_gc0_register(7, 0) +#define write_gc0_hwrena(val) __write_32bit_gc0_register(7, 0, val) + +#define read_gc0_badvaddr() __read_ulong_gc0_register(8, 0) +#define write_gc0_badvaddr(val) __write_ulong_gc0_register(8, 0, val) + +#define read_gc0_badinstr() __read_32bit_gc0_register(8, 1) +#define write_gc0_badinstr(val) __write_32bit_gc0_register(8, 1, val) + +#define read_gc0_badinstrp() __read_32bit_gc0_register(8, 2) +#define write_gc0_badinstrp(val) __write_32bit_gc0_register(8, 2, val) + +#define read_gc0_count() __read_32bit_gc0_register(9, 0) + +#define read_gc0_entryhi() __read_ulong_gc0_register(10, 0) +#define write_gc0_entryhi(val) __write_ulong_gc0_register(10, 0, val) + +#define read_gc0_compare() __read_32bit_gc0_register(11, 0) +#define write_gc0_compare(val) __write_32bit_gc0_register(11, 0, val) + +#define read_gc0_status() __read_32bit_gc0_register(12, 0) +#define write_gc0_status(val) __write_32bit_gc0_register(12, 0, val) + +#define read_gc0_intctl() __read_32bit_gc0_register(12, 1) +#define write_gc0_intctl(val) __write_32bit_gc0_register(12, 1, val) + +#define read_gc0_cause() __read_32bit_gc0_register(13, 0) +#define write_gc0_cause(val) __write_32bit_gc0_register(13, 0, val) + +#define read_gc0_epc() __read_ulong_gc0_register(14, 0) +#define write_gc0_epc(val) __write_ulong_gc0_register(14, 0, val) + +#define read_gc0_ebase() __read_32bit_gc0_register(15, 1) +#define write_gc0_ebase(val) __write_32bit_gc0_register(15, 1, val) + +#define read_gc0_ebase_64() __read_64bit_gc0_register(15, 1) +#define write_gc0_ebase_64(val) __write_64bit_gc0_register(15, 1, val) + +#define read_gc0_config() __read_32bit_gc0_register(16, 0) +#define read_gc0_config1() __read_32bit_gc0_register(16, 1) +#define read_gc0_config2() __read_32bit_gc0_register(16, 2) +#define read_gc0_config3() __read_32bit_gc0_register(16, 3) +#define read_gc0_config4() __read_32bit_gc0_register(16, 4) +#define read_gc0_config5() __read_32bit_gc0_register(16, 5) +#define read_gc0_config6() __read_32bit_gc0_register(16, 6) +#define read_gc0_config7() __read_32bit_gc0_register(16, 7) +#define write_gc0_config(val) __write_32bit_gc0_register(16, 0, val) +#define write_gc0_config1(val) __write_32bit_gc0_register(16, 1, val) +#define write_gc0_config2(val) __write_32bit_gc0_register(16, 2, val) +#define write_gc0_config3(val) __write_32bit_gc0_register(16, 3, val) +#define write_gc0_config4(val) __write_32bit_gc0_register(16, 4, val) +#define write_gc0_config5(val) __write_32bit_gc0_register(16, 5, val) +#define write_gc0_config6(val) __write_32bit_gc0_register(16, 6, val) +#define write_gc0_config7(val) __write_32bit_gc0_register(16, 7, val) + +#define read_gc0_watchlo0() __read_ulong_gc0_register(18, 0) +#define read_gc0_watchlo1() __read_ulong_gc0_register(18, 1) +#define read_gc0_watchlo2() __read_ulong_gc0_register(18, 2) +#define read_gc0_watchlo3() __read_ulong_gc0_register(18, 3) +#define read_gc0_watchlo4() __read_ulong_gc0_register(18, 4) +#define read_gc0_watchlo5() __read_ulong_gc0_register(18, 5) +#define read_gc0_watchlo6() __read_ulong_gc0_register(18, 6) +#define read_gc0_watchlo7() __read_ulong_gc0_register(18, 7) +#define write_gc0_watchlo0(val) __write_ulong_gc0_register(18, 0, val) +#define write_gc0_watchlo1(val) __write_ulong_gc0_register(18, 1, val) +#define write_gc0_watchlo2(val) __write_ulong_gc0_register(18, 2, val) +#define write_gc0_watchlo3(val) __write_ulong_gc0_register(18, 3, val) +#define write_gc0_watchlo4(val) __write_ulong_gc0_register(18, 4, val) +#define write_gc0_watchlo5(val) __write_ulong_gc0_register(18, 5, val) +#define write_gc0_watchlo6(val) __write_ulong_gc0_register(18, 6, val) +#define write_gc0_watchlo7(val) __write_ulong_gc0_register(18, 7, val) + +#define read_gc0_watchhi0() __read_32bit_gc0_register(19, 0) +#define read_gc0_watchhi1() __read_32bit_gc0_register(19, 1) +#define read_gc0_watchhi2() __read_32bit_gc0_register(19, 2) +#define read_gc0_watchhi3() __read_32bit_gc0_register(19, 3) +#define read_gc0_watchhi4() __read_32bit_gc0_register(19, 4) +#define read_gc0_watchhi5() __read_32bit_gc0_register(19, 5) +#define read_gc0_watchhi6() __read_32bit_gc0_register(19, 6) +#define read_gc0_watchhi7() __read_32bit_gc0_register(19, 7) +#define write_gc0_watchhi0(val) __write_32bit_gc0_register(19, 0, val) +#define write_gc0_watchhi1(val) __write_32bit_gc0_register(19, 1, val) +#define write_gc0_watchhi2(val) __write_32bit_gc0_register(19, 2, val) +#define write_gc0_watchhi3(val) __write_32bit_gc0_register(19, 3, val) +#define write_gc0_watchhi4(val) __write_32bit_gc0_register(19, 4, val) +#define write_gc0_watchhi5(val) __write_32bit_gc0_register(19, 5, val) +#define write_gc0_watchhi6(val) __write_32bit_gc0_register(19, 6, val) +#define write_gc0_watchhi7(val) __write_32bit_gc0_register(19, 7, val) + +#define read_gc0_xcontext() __read_ulong_gc0_register(20, 0) +#define write_gc0_xcontext(val) __write_ulong_gc0_register(20, 0, val) + +#define read_gc0_perfctrl0() __read_32bit_gc0_register(25, 0) +#define write_gc0_perfctrl0(val) __write_32bit_gc0_register(25, 0, val) +#define read_gc0_perfcntr0() __read_32bit_gc0_register(25, 1) +#define write_gc0_perfcntr0(val) __write_32bit_gc0_register(25, 1, val) +#define read_gc0_perfcntr0_64() __read_64bit_gc0_register(25, 1) +#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register(25, 1, val) +#define read_gc0_perfctrl1() __read_32bit_gc0_register(25, 2) +#define write_gc0_perfctrl1(val) __write_32bit_gc0_register(25, 2, val) +#define read_gc0_perfcntr1() __read_32bit_gc0_register(25, 3) +#define write_gc0_perfcntr1(val) __write_32bit_gc0_register(25, 3, val) +#define read_gc0_perfcntr1_64() __read_64bit_gc0_register(25, 3) +#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register(25, 3, val) +#define read_gc0_perfctrl2() __read_32bit_gc0_register(25, 4) +#define write_gc0_perfctrl2(val) __write_32bit_gc0_register(25, 4, val) +#define read_gc0_perfcntr2() __read_32bit_gc0_register(25, 5) +#define write_gc0_perfcntr2(val) __write_32bit_gc0_register(25, 5, val) +#define read_gc0_perfcntr2_64() __read_64bit_gc0_register(25, 5) +#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register(25, 5, val) +#define read_gc0_perfctrl3() __read_32bit_gc0_register(25, 6) +#define write_gc0_perfctrl3(val) __write_32bit_gc0_register(25, 6, val) +#define read_gc0_perfcntr3() __read_32bit_gc0_register(25, 7) +#define write_gc0_perfcntr3(val) __write_32bit_gc0_register(25, 7, val) +#define read_gc0_perfcntr3_64() __read_64bit_gc0_register(25, 7) +#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register(25, 7, val) + +#define read_gc0_errorepc() __read_ulong_gc0_register(30, 0) +#define write_gc0_errorepc(val) __write_ulong_gc0_register(30, 0, val) + +#define read_gc0_kscratch1() __read_ulong_gc0_register(31, 2) +#define read_gc0_kscratch2() __read_ulong_gc0_register(31, 3) +#define read_gc0_kscratch3() __read_ulong_gc0_register(31, 4) +#define read_gc0_kscratch4() __read_ulong_gc0_register(31, 5) +#define read_gc0_kscratch5() __read_ulong_gc0_register(31, 6) +#define read_gc0_kscratch6() __read_ulong_gc0_register(31, 7) +#define write_gc0_kscratch1(val) __write_ulong_gc0_register(31, 2, val) +#define write_gc0_kscratch2(val) __write_ulong_gc0_register(31, 3, val) +#define write_gc0_kscratch3(val) __write_ulong_gc0_register(31, 4, val) +#define write_gc0_kscratch4(val) __write_ulong_gc0_register(31, 5, val) +#define write_gc0_kscratch5(val) __write_ulong_gc0_register(31, 6, val) +#define write_gc0_kscratch6(val) __write_ulong_gc0_register(31, 7, val) /* * Macros to access the floating point coprocessor control registers @@ -2421,6 +2485,8 @@ static inline void tlb_write_random(void) ".set reorder"); } +#ifdef TOOLCHAIN_SUPPORTS_VIRT + /* * Guest TLB operations. * @@ -2479,6 +2545,53 @@ static inline void guest_tlbinvf(void) ".set pop"); } +#else /* TOOLCHAIN_SUPPORTS_VIRT */ + +/* + * Guest TLB operations. + * + * It is responsibility of the caller to take care of any TLB hazards. + */ +static inline void guest_tlb_probe(void) +{ + __asm__ __volatile__( + "# tlbgp\n\t" + ".word 0x42000010"); +} + +static inline void guest_tlb_read(void) +{ + __asm__ __volatile__( + "# tlbgr\n\t" + ".word 0x42000009"); +} + +static inline void guest_tlb_write_indexed(void) +{ + __asm__ __volatile__( + "# tlbgwi\n\t" + ".word 0x4200000a"); +} + +static inline void guest_tlb_write_random(void) +{ + __asm__ __volatile__( + "# tlbgwr\n\t" + ".word 0x4200000e"); +} + +/* + * Guest TLB Invalidate Flush + */ +static inline void guest_tlbinvf(void) +{ + __asm__ __volatile__( + "# tlbginvf\n\t" + ".word 0x4200000c"); +} + +#endif /* !TOOLCHAIN_SUPPORTS_VIRT */ + /* * Manipulate bits in a register. */ -- cgit v1.2.3-59-g8ed1b From 6241bf6a59a41c7ca742c043416b6d57109c6b5d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 16 May 2016 19:51:54 +0200 Subject: MIPS: ath79: make ath79_ddr_ctrl_init() compatible for newer SoCs AR913x, AR724x and AR933x are the only SoCs where the ath79_ddr_wb_flush_base starts at 0x7c, all newer SoCs use 0x9c Invert the logic to make the code compatible with AR95xx Signed-off-by: Felix Fietkau Cc: albeu@free.fr Cc: sergei.shtylyov@cogentembedded.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13257/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 3cedd1f95e0f..84d4502755fc 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -46,12 +46,12 @@ void ath79_ddr_ctrl_init(void) { ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE); - if (soc_is_ar71xx() || soc_is_ar934x()) { - ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; - ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; - } else { + if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) { ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; ath79_ddr_pci_win_base = 0; + } else { + ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; + ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; } } EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init); -- cgit v1.2.3-59-g8ed1b From 9184dc8ffa56844352b3b9860e562ec4ee41176f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 16 May 2016 19:51:55 +0200 Subject: MIPS: ath79: fix regression in PCI window initialization ath79_ddr_pci_win_base has the type void __iomem *, so register offsets need to be a multiple of 4. Cc: Alban Bedel Fixes: 24b0e3e84fbf ("MIPS: ath79: Improve the DDR controller interface") Signed-off-by: Felix Fietkau Cc: sergei.shtylyov@cogentembedded.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13258/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/common.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 84d4502755fc..d071a3a0f876 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -76,14 +76,14 @@ void ath79_ddr_set_pci_windows(void) { BUG_ON(!ath79_ddr_pci_win_base); - __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0); - __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1); - __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2); - __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3); - __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4); - __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5); - __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6); - __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7); + __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0); + __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4); + __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8); + __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc); + __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10); + __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14); + __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18); + __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c); } EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); -- cgit v1.2.3-59-g8ed1b From 6e4ad1b413604b9130bdbe532aafdbd47ff5318e Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Tue, 17 May 2016 10:35:52 +0530 Subject: MIPS: pic32mzda: fix getting timer clock rate. PIC32 clock driver is now implemented as platform driver instead of as part of of_clk_init(). It meants all the clock modules are available quite late in the boot sequence. So request for CPU clock by clk_get_sys() and clk_get_rate() to find c0_timer rate fails. To fix this use PIC32 specific early clock functions implemented for early console support. Signed-off-by: Purna Chandra Mandal Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: Joshua Henderson Patchwork: https://patchwork.linux-mips.org/patch/13262/ Signed-off-by: Ralf Baechle --- arch/mips/pic32/pic32mzda/time.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/pic32/pic32mzda/time.c b/arch/mips/pic32/pic32mzda/time.c index ca6a62bb10db..62a0a78b6c64 100644 --- a/arch/mips/pic32/pic32mzda/time.c +++ b/arch/mips/pic32/pic32mzda/time.c @@ -11,13 +11,12 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ -#include #include #include #include +#include #include #include -#include #include @@ -58,16 +57,12 @@ unsigned int get_c0_compare_int(void) void __init plat_time_init(void) { - struct clk *clk; + unsigned long rate = pic32_get_pbclk(7); of_clk_init(NULL); - clk = clk_get_sys("cpu_clk", NULL); - if (IS_ERR(clk)) - panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); - clk_prepare_enable(clk); - pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); - mips_hpt_frequency = clk_get_rate(clk) / 2; + pr_info("CPU Clock: %ldMHz\n", rate / 1000000); + mips_hpt_frequency = rate / 2; clocksource_probe(); } -- cgit v1.2.3-59-g8ed1b