From f25319d2cb439249a6859f53ad42ffa332b0acba Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 16 Oct 2015 23:09:57 +0200 Subject: [PATCH 001/120] MIPS: atomic: Fix comment describing atomic64_add_unless's return value. Signed-off-by: Ralf Baechle Fixes: f24219b4e90cf70ec4a211b17fbabc725a0ddf3c (cherry picked from commit f0a232cde7be18a207fd057dd79bbac8a0a45dec) --- arch/mips/include/asm/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 4c42fd9af777..b34781752244 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -507,7 +507,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) * @u: ...unless v is equal to u. * * Atomically adds @a to @v, so long as it was not @u. - * Returns the old value of @v. + * Returns true iff @v was not @u. */ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) { From 05513992c69d159e698bb4b5f651abd0ceff525c Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:34:08 +0200 Subject: [PATCH 002/120] MIPS: Remove invalid check Unsigned values cannot be lesser than zero. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [ralf@linux-mips.org: Chris Dearman's original commit 9318c51acd9689505850152cc98277a6d6f2d752 ([MIPS] MIPS32/MIPS64 secondary cache management) introduced these less than zero checks in 2.6.18.] [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Cc: linux-kernel@vger.kernel.org Cc: Bartlomiej Zolnierkiewicz Cc: Marek Szyprowski Cc: Markos Chandras Cc: Chris Dearman Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11165/ Signed-off-by: Ralf Baechle --- arch/mips/mm/sc-mips.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 53ea8391f9bb..1755187a6545 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -162,13 +162,13 @@ static inline int __init mips_sc_probe(void) return 0; tmp = (config2 >> 8) & 0x0f; - if (0 <= tmp && tmp <= 7) + if (tmp <= 7) c->scache.sets = 64 << tmp; else return 0; tmp = (config2 >> 0) & 0x0f; - if (0 <= tmp && tmp <= 7) + if (tmp <= 7) c->scache.ways = tmp + 1; else return 0; From c1a0e9bc885d46e519fd87d35af6a7937abfb986 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:07:41 -0700 Subject: [PATCH 003/120] MIPS: Allow compact branch policy to be changed When debugging it can be helpful to change the policy for compiler use of MIPSr6 compact branches, in order to rule out or home in on their involvement in bugs. Allow the GCC -mcompact-branches= flag to be set via Kconfig under the "Kernel hacking" menu. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11178/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig.debug | 36 ++++++++++++++++++++++++++++++++++++ arch/mips/Makefile | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index e250524021ac..13d796547ebd 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -113,4 +113,40 @@ config SPINLOCK_TEST help Add several files to the debugfs to test spinlock speed. +if CPU_MIPSR6 + +choice + prompt "Compact branch policy" + default MIPS_COMPACT_BRANCHES_OPTIMAL + +config MIPS_COMPACT_BRANCHES_NEVER + bool "Never (force delay slot branches)" + help + Pass the -mcompact-branches=never flag to the compiler in order to + force it to always emit branches with delay slots, and make no use + of the compact branch instructions introduced by MIPSr6. This is + useful if you suspect there may be an issue with compact branches in + either the compiler or the CPU. + +config MIPS_COMPACT_BRANCHES_OPTIMAL + bool "Optimal (use where beneficial)" + help + Pass the -mcompact-branches=optimal flag to the compiler in order for + it to make use of compact branch instructions where it deems them + beneficial, and use branches with delay slots elsewhere. This is the + default compiler behaviour, and should be used unless you have a + reason to choose otherwise. + +config MIPS_COMPACT_BRANCHES_ALWAYS + bool "Always (force compact branches)" + help + Pass the -mcompact-branches=always flag to the compiler in order to + force it to always emit compact branches, making no use of branch + instructions with delay slots. This can result in more compact code + which may be beneficial in some scenarios. + +endchoice + +endif # CPU_MIPSR6 + endmenu diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 252e347958f3..3f70ba54ae21 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -204,6 +204,10 @@ toolchain-msa := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$( cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA endif +cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER) += -mcompact-branches=never +cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal +cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS) += -mcompact-branches=always + # # Firmware support # From 37f2a174c491dee09844491e5869f5701894ade4 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:10:53 -0700 Subject: [PATCH 004/120] MIPS: Introduce API for enabling & disabling L2 prefetch Introduce new functions in struct bcache_ops to enable & disable L2 cache prefetching, and to retrieve the current state of L2 prefetching. This will be used in later patches. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11179/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/bcache.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/mips/include/asm/bcache.h b/arch/mips/include/asm/bcache.h index 8c34484cea82..a00857b135c3 100644 --- a/arch/mips/include/asm/bcache.h +++ b/arch/mips/include/asm/bcache.h @@ -9,6 +9,7 @@ #ifndef _ASM_BCACHE_H #define _ASM_BCACHE_H +#include /* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent, chipset implemented caches. On machines with other CPUs the CPU does the @@ -18,6 +19,9 @@ struct bcache_ops { void (*bc_disable)(void); void (*bc_wback_inv)(unsigned long page, unsigned long size); void (*bc_inv)(unsigned long page, unsigned long size); + void (*bc_prefetch_enable)(void); + void (*bc_prefetch_disable)(void); + bool (*bc_prefetch_is_enabled)(void); }; extern void indy_sc_init(void); @@ -46,6 +50,26 @@ static inline void bc_inv(unsigned long page, unsigned long size) bcops->bc_inv(page, size); } +static inline void bc_prefetch_enable(void) +{ + if (bcops->bc_prefetch_enable) + bcops->bc_prefetch_enable(); +} + +static inline void bc_prefetch_disable(void) +{ + if (bcops->bc_prefetch_disable) + bcops->bc_prefetch_disable(); +} + +static inline bool bc_prefetch_is_enabled(void) +{ + if (bcops->bc_prefetch_is_enabled) + return bcops->bc_prefetch_is_enabled(); + + return false; +} + #else /* !defined(CONFIG_BOARD_SCACHE) */ /* Not R4000 / R4400 / R4600 / R5000. */ @@ -54,6 +78,9 @@ static inline void bc_inv(unsigned long page, unsigned long size) #define bc_disable() do { } while (0) #define bc_wback_inv(page, size) do { } while (0) #define bc_inv(page, size) do { } while (0) +#define bc_prefetch_enable() do { } while (0) +#define bc_prefetch_disable() do { } while (0) +#define bc_prefetch_is_enabled() 0 #endif /* !defined(CONFIG_BOARD_SCACHE) */ From 4d035516921713b41bb279682e53b4fbd5a87232 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:10:54 -0700 Subject: [PATCH 005/120] MIPS: Enable L2 prefetching for CM >= 2.5 On systems with CM 2.5 & beyond there may be L2 prefetch units present which are not enabled by default. Detect them, configuring & enabling prefetching when available. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11180/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 17 +++++++++ arch/mips/mm/sc-mips.c | 61 ++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 1f1927ab4269..d66d0e00365b 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -195,6 +195,8 @@ BUILD_CM_R_(gic_status, MIPS_CM_GCB_OFS + 0xd0) BUILD_CM_R_(cpc_status, MIPS_CM_GCB_OFS + 0xf0) 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) /* Core Local & Core Other register accessor functions */ BUILD_CM_Cx_RW(reset_release, 0x00) @@ -245,6 +247,7 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) ((minor) << CM_GCR_REV_MINOR_SHF)) #define CM_REV_CM2 CM_ENCODE_REV(6, 0) +#define CM_REV_CM2_5 CM_ENCODE_REV(7, 0) #define CM_REV_CM3 CM_ENCODE_REV(8, 0) /* GCR_ERROR_CAUSE register fields */ @@ -321,6 +324,20 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_SYS_CONFIG2_MAXVPW_SHF 0 #define CM_GCR_SYS_CONFIG2_MAXVPW_MSK (_ULCAST_(0xf) << 0) +/* GCR_L2_PFT_CONTROL register fields */ +#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_SHF 12 +#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK (_ULCAST_(0xfffff) << 12) +#define CM_GCR_L2_PFT_CONTROL_PFTEN_SHF 8 +#define CM_GCR_L2_PFT_CONTROL_PFTEN_MSK (_ULCAST_(0x1) << 8) +#define CM_GCR_L2_PFT_CONTROL_NPFT_SHF 0 +#define CM_GCR_L2_PFT_CONTROL_NPFT_MSK (_ULCAST_(0xff) << 0) + +/* GCR_L2_PFT_CONTROL_B register fields */ +#define CM_GCR_L2_PFT_CONTROL_B_CEN_SHF 8 +#define CM_GCR_L2_PFT_CONTROL_B_CEN_MSK (_ULCAST_(0x1) << 8) +#define CM_GCR_L2_PFT_CONTROL_B_PORTID_SHF 0 +#define CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK (_ULCAST_(0xff) << 0) + /* GCR_Cx_COHERENCE register fields */ #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF 0 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK (_ULCAST_(0xff) << 0) diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 1755187a6545..3bd0597d9c3d 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -51,11 +51,69 @@ static void mips_sc_disable(void) /* L2 cache is permanently enabled */ } +static void mips_sc_prefetch_enable(void) +{ + unsigned long pftctl; + + if (mips_cm_revision() < CM_REV_CM2_5) + return; + + /* + * If there is one or more L2 prefetch unit present then enable + * prefetching for both code & data, for all ports. + */ + pftctl = read_gcr_l2_pft_control(); + if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) { + pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK; + pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK; + pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK; + write_gcr_l2_pft_control(pftctl); + + pftctl = read_gcr_l2_pft_control_b(); + pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK; + pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK; + write_gcr_l2_pft_control_b(pftctl); + } +} + +static void mips_sc_prefetch_disable(void) +{ + unsigned long pftctl; + + if (mips_cm_revision() < CM_REV_CM2_5) + return; + + pftctl = read_gcr_l2_pft_control(); + pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK; + write_gcr_l2_pft_control(pftctl); + + pftctl = read_gcr_l2_pft_control_b(); + pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK; + pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK; + write_gcr_l2_pft_control_b(pftctl); +} + +static bool mips_sc_prefetch_is_enabled(void) +{ + unsigned long pftctl; + + if (mips_cm_revision() < CM_REV_CM2_5) + return false; + + pftctl = read_gcr_l2_pft_control(); + if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK)) + return false; + return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK); +} + static struct bcache_ops mips_sc_ops = { .bc_enable = mips_sc_enable, .bc_disable = mips_sc_disable, .bc_wback_inv = mips_sc_wback_inv, - .bc_inv = mips_sc_inv + .bc_inv = mips_sc_inv, + .bc_prefetch_enable = mips_sc_prefetch_enable, + .bc_prefetch_disable = mips_sc_prefetch_disable, + .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled, }; /* @@ -186,6 +244,7 @@ int mips_sc_init(void) int found = mips_sc_probe(); if (found) { mips_sc_enable(); + mips_sc_prefetch_enable(); bcops = &mips_sc_ops; } return found; From 75dcfc1d678d76a82288c043bfd5bfc0fbd43b49 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:10:55 -0700 Subject: [PATCH 006/120] MIPS: Declare mips_debugfs_dir in a header We have many extern declarations of mips_debugfs_dir through arch/mips/ in various C files. Unify them by declaring mips_debugfs_dir in a header, including it in each affected C file & removing the duplicate declarations. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Alexander Sverdlin Cc: Masahiro Yamada Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: linux-kernel@vger.kernel.org Cc: Joe Perches Cc: Jaedon Shin Cc: James Hogan Cc: David Daney Cc: Zubair Lutfullah Kakakhel Cc: Markos Chandras Cc: James Cowgill Patchwork: https://patchwork.linux-mips.org/patch/11181/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/debug.h | 22 ++++++++++++++++++++++ arch/mips/kernel/mips-r2-to-r6-emul.c | 2 +- arch/mips/kernel/segment.c | 2 +- arch/mips/kernel/setup.c | 1 + arch/mips/kernel/spinlock_test.c | 4 +--- arch/mips/kernel/unaligned.c | 2 +- arch/mips/math-emu/me-debugfs.c | 2 +- 7 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 arch/mips/include/asm/debug.h diff --git a/arch/mips/include/asm/debug.h b/arch/mips/include/asm/debug.h new file mode 100644 index 000000000000..254f00deb9d5 --- /dev/null +++ b/arch/mips/include/asm/debug.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * + * 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 __MIPS_ASM_DEBUG_H__ +#define __MIPS_ASM_DEBUG_H__ + +#include + +/* + * mips_debugfs_dir corresponds to the "mips" directory at the top level + * of the DebugFS hierarchy. MIPS-specific DebugFS entires should be + * placed beneath this directory. + */ +extern struct dentry *mips_debugfs_dir; + +#endif /* __MIPS_ASM_DEBUG_H__ */ diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index f2977f00911b..1f5aac7f9ec3 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -2363,7 +2364,6 @@ static const struct file_operations mipsr2_clear_fops = { static int __init mipsr2_init_debugfs(void) { - extern struct dentry *mips_debugfs_dir; struct dentry *mipsr2_emul; if (!mips_debugfs_dir) diff --git a/arch/mips/kernel/segment.c b/arch/mips/kernel/segment.c index 076ead2a9859..87bc74a5a518 100644 --- a/arch/mips/kernel/segment.c +++ b/arch/mips/kernel/segment.c @@ -10,6 +10,7 @@ #include #include #include +#include #include static void build_segment_config(char *str, unsigned int cfg) @@ -91,7 +92,6 @@ static const struct file_operations segments_fops = { static int __init segments_info(void) { - extern struct dentry *mips_debugfs_dir; struct dentry *segments; if (cpu_has_segments) { diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 479515109e5b..5b46b672c939 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/kernel/spinlock_test.c b/arch/mips/kernel/spinlock_test.c index 39f7ab7b0426..f7d86955d1b8 100644 --- a/arch/mips/kernel/spinlock_test.c +++ b/arch/mips/kernel/spinlock_test.c @@ -5,7 +5,7 @@ #include #include #include - +#include static int ss_get(void *data, u64 *val) { @@ -115,8 +115,6 @@ static int multi_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n"); - -extern struct dentry *mips_debugfs_dir; static int __init spinlock_test(void) { struct dentry *d; diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 990354dd6bde..490cea569d57 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -2295,7 +2296,6 @@ sigbus: } #ifdef CONFIG_DEBUG_FS -extern struct dentry *mips_debugfs_dir; static int __init debugfs_unaligned(void) { struct dentry *d; diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c index 506a67a98cdf..be650ed7db59 100644 --- a/arch/mips/math-emu/me-debugfs.c +++ b/arch/mips/math-emu/me-debugfs.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,6 @@ static int fpuemu_stat_get(void *data, u64 *val) } DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); -extern struct dentry *mips_debugfs_dir; static int __init debugfs_fpuemu(void) { struct dentry *d, *dir; From d478b088a2f74fc8f34af7ceed86fa7640ca8610 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:10:56 -0700 Subject: [PATCH 007/120] MIPS: Allow L2 prefetch to be configured via debugfs When debugging or examining the performance of a system it can be useful to examine the effect of L2 prefetching. Provide an optional debugfs entry to allow a user to enable or disable L2 prefetching. 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/11182/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig.debug | 10 +++++ arch/mips/mm/Makefile | 1 + arch/mips/mm/sc-debugfs.c | 81 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 arch/mips/mm/sc-debugfs.c diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 13d796547ebd..b43e288ec567 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -149,4 +149,14 @@ endchoice endif # CPU_MIPSR6 +config SCACHE_DEBUGFS + bool "L2 cache debugfs entries" + depends on DEBUG_FS + help + Enable this to allow parts of the L2 cache configuration, such as + whether or not prefetching is enabled, to be exposed to userland + via debugfs. + + If unsure, say N. + endmenu diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index 67ede4ef9b8d..b4c64bd3f723 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o +obj-$(CONFIG_SCACHE_DEBUGFS) += sc-debugfs.o diff --git a/arch/mips/mm/sc-debugfs.c b/arch/mips/mm/sc-debugfs.c new file mode 100644 index 000000000000..5eefe3281b24 --- /dev/null +++ b/arch/mips/mm/sc-debugfs.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Paul Burton + * + * 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. + */ + +#include +#include +#include +#include +#include + +static ssize_t sc_prefetch_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + bool enabled = bc_prefetch_is_enabled(); + char buf[3]; + + buf[0] = enabled ? 'Y' : 'N'; + buf[1] = '\n'; + buf[2] = 0; + + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static ssize_t sc_prefetch_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char buf[32]; + ssize_t buf_size; + bool enabled; + int err; + + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + buf[buf_size] = '\0'; + err = strtobool(buf, &enabled); + if (err) + return err; + + if (enabled) + bc_prefetch_enable(); + else + bc_prefetch_disable(); + + return count; +} + +static const struct file_operations sc_prefetch_fops = { + .open = simple_open, + .llseek = default_llseek, + .read = sc_prefetch_read, + .write = sc_prefetch_write, +}; + +static int __init sc_debugfs_init(void) +{ + struct dentry *dir, *file; + + if (!mips_debugfs_dir) + return -ENODEV; + + dir = debugfs_create_dir("l2cache", mips_debugfs_dir); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + file = debugfs_create_file("prefetch", S_IRUGO | S_IWUSR, dir, + NULL, &sc_prefetch_fops); + if (IS_ERR(file)) + return PTR_ERR(file); + + return 0; +} +late_initcall(sc_debugfs_init); From 1ee3630a3e57f38f688a6f0a5f9edbd8a0d7201f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 29 Sep 2015 12:19:48 +0200 Subject: [PATCH 008/120] MIPS: Use ARCH_USE_BUILTIN_BSWAP. ARCH_USE_BUILTIN_BSWAP will use __builtin_bswap16(), __builtin_bswap32() and __builtin_bswap64() where available. This allows better instruction scheduling. On pre-R2 processors it will result in 32 bit and 64 bit swapping being performed in a call to a __bswapsi2() rsp. __bswapdi2() functions, so we add these, too. For a 4.2 kernel with GCC 4.9 this yields the following kernel sizes: text data bss dec hex filename 3996071 155804 88992 4240867 40b5e3 vmlinux ip22 baseline 3985687 159900 88992 4234579 409d53 vmlinux ip22 + bswap patch 6913157 378552 251024 7542733 7317cd vmlinux ip27 baseline 6878581 378552 251024 7508157 7290bd vmlinux ip27 + bswap patch 5773777 268752 187424 6229953 5f0fc1 vmlinux malta baseline 5773401 268752 187424 6229577 5f0e49 vmlinux malta + bswap patch Presumably the code size improvments yield better cache hit rate thus better performance compensating for the extra function call but this will still need to be benchmarked. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/lib/Makefile | 2 +- arch/mips/lib/bswapdi.c | 15 +++++++++++++++ arch/mips/lib/bswapsi.c | 11 +++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 arch/mips/lib/bswapdi.c create mode 100644 arch/mips/lib/bswapsi.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e3aa5b0b4ef1..c08e7016c77a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -5,6 +5,7 @@ config MIPS select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO select ARCH_USE_CMPXCHG_LOCKREF if 64BIT + select ARCH_USE_BUILTIN_BSWAP select HAVE_CONTEXT_TRACKING select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1e9e900cd3c3..0344e575f522 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -15,4 +15,4 @@ obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o # libgcc-style stuff needed in the kernel -obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o +obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c new file mode 100644 index 000000000000..77e5f9c1f005 --- /dev/null +++ b/arch/mips/lib/bswapdi.c @@ -0,0 +1,15 @@ +#include + +unsigned long long __bswapdi2(unsigned long long u) +{ + return (((u) & 0xff00000000000000ull) >> 56) | + (((u) & 0x00ff000000000000ull) >> 40) | + (((u) & 0x0000ff0000000000ull) >> 24) | + (((u) & 0x000000ff00000000ull) >> 8) | + (((u) & 0x00000000ff000000ull) << 8) | + (((u) & 0x0000000000ff0000ull) << 24) | + (((u) & 0x000000000000ff00ull) << 40) | + (((u) & 0x00000000000000ffull) << 56); +} + +EXPORT_SYMBOL(__bswapdi2); diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c new file mode 100644 index 000000000000..2b302ff121d2 --- /dev/null +++ b/arch/mips/lib/bswapsi.c @@ -0,0 +1,11 @@ +#include + +unsigned int __bswapsi2(unsigned int u) +{ + return (((u) & 0xff000000) >> 24) | + (((u) & 0x00ff0000) >> 8) | + (((u) & 0x0000ff00) << 8) | + (((u) & 0x000000ff) << 24); +} + +EXPORT_SYMBOL(__bswapsi2); From 0503b69729f6ba83eacaf4dc97e54d55b7f1feba Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 5 Oct 2015 13:31:17 +0200 Subject: [PATCH 009/120] MIPS: JZ4740: Use PWM lookup table Associate the PWM with the pwm-beeper device using a PWM lookup table. This will eventually allow the legacy function calls to pwm_request() to be removed from all consumer drivers. Signed-off-by: Thierry Reding Cc: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11261/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/board-qi_lb60.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 459cb017306c..d6f7e39ea687 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -399,13 +400,15 @@ static struct platform_device avt2_usb_regulator_device = { } }; +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, - .dev = { - .platform_data = (void *)4, - }, }; /* charger */ @@ -491,6 +494,8 @@ static int __init qi_lb60_init_platform_devices(void) 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, ARRAY_SIZE(jz_platform_devices)); From ee42a3344cc43bb404160ecb12038825638fcbf4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 5 Oct 2015 14:42:37 +0200 Subject: [PATCH 010/120] MIPS: JZ4740: Remove unused linux/leds_pwm.h include The board code never sets up a leds-pwm device, so including the header is not necessary. Signed-off-by: Thierry Reding Acked-by: Lars-Peter Clausen Cc: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11262/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/board-qi_lb60.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index d6f7e39ea687..934b15b5b575 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -35,8 +35,6 @@ #include #include -#include - #include #include "clock.h" From a13c996249a5ca7635853a4e7e15033393575e46 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:15:22 -0700 Subject: [PATCH 011/120] MIPS: traps: tidy up ebase calculation Rather than #ifdef on CONFIG_KVM_GUEST & redefine the guest kseg0 base locally, make use of the CAC_BASE macro which has the correct value in both cases. Signed-off-by: Paul Burton Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: linux-kernel@vger.kernel.org Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11183/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fdb392b27e81..4e106d52f304 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -2204,12 +2205,8 @@ void __init trap_init(void) ebase = (unsigned long) __alloc_bootmem(size, 1 << fls(size), 0); } else { -#ifdef CONFIG_KVM_GUEST -#define KVM_GUEST_KSEG0 0x40000000 - ebase = KVM_GUEST_KSEG0; -#else - ebase = CKSEG0; -#endif + ebase = CAC_BASE; + if (cpu_has_mips_r2_r6) ebase += (read_c0_ebase() & 0x3ffff000); } From 6759657341100ce876e69946365ef91907e3015e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:16:39 -0700 Subject: [PATCH 012/120] MIPS: Allow 24Hz timer frequency A boundary exists beyond which the timer frequency becomes high enough that timer interrupts saturate the system and either cause it to slow to a crawl or stop functioning entirely. Where that boundary lies depends upon a number of factors such as the overhead of each interrupt and the overall speed of the CPU, but correlates strongly with the clock frequency at which the CPU runs. When running on emulators during bringup or debug of a CPU that clock frequency is very low, which results in the boundary at which the timer frequency becomes unsustainable being very low. The current minimum of 48Hz pushes against boundary in certain situations in current systems. Allow the kernel to be configured for a 24Hz timer frequency in order to avoid problems on such slow running systems. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11184/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c08e7016c77a..1943377ea491 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2530,6 +2530,9 @@ choice help Allows the configuration of the timer frequency. + config HZ_24 + bool "24 HZ" if SYS_SUPPORTS_24HZ || SYS_SUPPORTS_ARBIT_HZ + config HZ_48 bool "48 HZ" if SYS_SUPPORTS_48HZ || SYS_SUPPORTS_ARBIT_HZ @@ -2553,6 +2556,9 @@ choice endchoice +config SYS_SUPPORTS_24HZ + bool + config SYS_SUPPORTS_48HZ bool @@ -2576,13 +2582,18 @@ config SYS_SUPPORTS_1024HZ config SYS_SUPPORTS_ARBIT_HZ bool - default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \ - !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \ - !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \ + default y if !SYS_SUPPORTS_24HZ && \ + !SYS_SUPPORTS_48HZ && \ + !SYS_SUPPORTS_100HZ && \ + !SYS_SUPPORTS_128HZ && \ + !SYS_SUPPORTS_250HZ && \ + !SYS_SUPPORTS_256HZ && \ + !SYS_SUPPORTS_1000HZ && \ !SYS_SUPPORTS_1024HZ config HZ int + default 24 if HZ_24 default 48 if HZ_48 default 100 if HZ_100 default 128 if HZ_128 From 7784494ae7864a112d4858b2b494e0358ec412a1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:26:37 -0700 Subject: [PATCH 013/120] MIPS: Clarify mips_cm_is64 documentation The documentation for mips_cm_is64 implied that the width of the CM GCRs would change depending upon the CPU, which is not true. Reword the explanation to be clearer that the GCR width is purely dependent upon the version of the CM. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11185/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index d66d0e00365b..465a7c1f737b 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -36,12 +36,12 @@ extern phys_addr_t __mips_cm_phys_base(void); /* * mips_cm_is64 - determine CM register width * - * The CM register width is processor and CM specific. A 64-bit processor - * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit - * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs - * can be done either using regular 64-bit load/store instructions, or 32-bit - * load/store instruction on 32-bit register pairs. We opt for using 64-bit - * accesses on 64-bit CMs and kernels and 32-bit in any other case. + * The CM register width is determined by the version of the CM, with CM3 + * introducing 64 bit GCRs and all prior CM versions having 32 bit GCRs. + * However we may run a kernel built for MIPS32 on a system with 64 bit GCRs, + * or vice-versa. This variable indicates the width of the memory accesses + * that the kernel will perform to GCRs, which may differ from the actual + * width of the GCRs. * * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses. */ From 03b1b85d3d6c4f4153472afb7e015f1352e0c8f2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:26:38 -0700 Subject: [PATCH 014/120] MIPS: Don't read GCRs when a CM is not present Commit 3885c2b463f6 ("MIPS: CM: Add support for reporting CM cache errors") leads to Malta boards unconditionally reading CM GCRs upon bus errors, regardless of whether a CM is present. This is incorrect & will lead to further exceptions. Fix by moving the GCR reads to after the check for whether a CM is present. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11186/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-cm.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index b8ceee576cdf..10524ce769ae 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -252,7 +252,6 @@ int mips_cm_probe(void) void mips_cm_error_report(void) { - unsigned long revision = mips_cm_revision(); /* * CM3 has a 64-bit Error cause register with 0:57 containing the error * info and 63:58 the error type. For old CMs, everything is contained @@ -260,17 +259,21 @@ void mips_cm_error_report(void) * though the cm_error is u64, we will simply ignore the upper word * for CM2. */ - u64 cm_error = read_gcr_error_cause(); - int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF + - ((revision >= CM_REV_CM3) ? 31 : 0); - unsigned long cm_addr = read_gcr_error_addr(); - unsigned long cm_other = read_gcr_error_mult(); - int ocause, cause; + u64 cm_error; + unsigned long revision, cm_addr, cm_other; + int ocause, cause, cm_error_cause_sft; char buf[256]; if (!mips_cm_present()) return; + revision = mips_cm_revision(); + cm_error = read_gcr_error_cause(); + cm_addr = read_gcr_error_addr(); + cm_other = read_gcr_error_mult(); + + cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF + + ((revision >= CM_REV_CM3) ? 31 : 0); cause = cm_error >> cm_error_cause_sft; if (!cause) From f88e632480baf223cad67ac553a6729535db6d74 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:26:39 -0700 Subject: [PATCH 015/120] MIPS: Avoid buffer overrun in mips_cm_error_report Commit 3885c2b463f6 ("MIPS: CM: Add support for reporting CM cache errors") added cases for decoding errors reported by CM3, but leaves the buf variable which is printed as a string uninitialised for cause values other than 1, 2 or 3. Fix by ensuring the buf variable is initialised to an empty string in such cases. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11187/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-cm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 10524ce769ae..88a8e21a51dd 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -366,6 +366,8 @@ void mips_cm_error_report(void) cm3_cmd_group[cmd_group_bits], cm3_cca_bits, 1 << mcp_bits, cm3_tr[cm3_tr_bits], sched_bit); + } else { + buf[0] = 0; } pr_err("CM_ERROR=%llx %s <%s>\n", cm_error, From b657a628661570adb301284084a5335302685269 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:26:40 -0700 Subject: [PATCH 016/120] MIPS: Allow read64 GCR accessors to work on MIPS32 kernels If we run a MIPS32 kernel on a system using CM3 we may still need to access 64 bit GCRs, as will be done in later patches. Allow this by having the read64_gcr_* accessor functions perform 2 x 32 bit reads on those systems. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11188/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 465a7c1f737b..7234fb7b3f22 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -125,7 +125,17 @@ static inline u32 read32_gcr_##name(void) \ \ static inline u64 read64_gcr_##name(void) \ { \ - return __raw_readq(addr_gcr_##name()); \ + void __iomem *addr = addr_gcr_##name(); \ + u64 ret; \ + \ + if (mips_cm_is64) { \ + ret = __raw_readq(addr); \ + } else { \ + ret = __raw_readl(addr); \ + ret |= (u64)__raw_readl(addr + 0x4) << 32; \ + } \ + \ + return ret; \ } \ \ static inline unsigned long read_gcr_##name(void) \ From 47b26a467dc7dacbeae9240af5a35fc2fec48650 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 10:26:41 -0700 Subject: [PATCH 017/120] MIPS: Always read full 64 bit CM error GCRs for CM3 CM3 has 64 bit GCR_ERROR_* registers, but the code in mips_cm_error_report was previously only reading 32 bits of it in MIPS32 kernels. Fix by splitting the reads for CM2 & CM3, and making use of the read64_ variants of the accessor function for CM3. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11189/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 3 ++ arch/mips/kernel/mips-cm.c | 72 +++++++++++++++++---------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 7234fb7b3f22..9261c003990a 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -11,6 +11,7 @@ #ifndef __MIPS_ASM_MIPS_CM_H__ #define __MIPS_ASM_MIPS_CM_H__ +#include #include #include #include @@ -263,6 +264,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) /* GCR_ERROR_CAUSE register fields */ #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF 27 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK (_ULCAST_(0x1f) << 27) +#define CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF 58 +#define CM3_GCR_ERROR_CAUSE_ERRTYPE_MSK GENMASK_ULL(63, 58) #define CM_GCR_ERROR_CAUSE_ERRINFO_SHF 0 #define CM_GCR_ERROR_CAUSE_ERRINGO_MSK (_ULCAST_(0x7ffffff) << 0) diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 88a8e21a51dd..02f7d7a41133 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -252,36 +252,26 @@ int mips_cm_probe(void) void mips_cm_error_report(void) { - /* - * CM3 has a 64-bit Error cause register with 0:57 containing the error - * info and 63:58 the error type. For old CMs, everything is contained - * in a single 32-bit register (0:26 and 31:27 respectively). Even - * though the cm_error is u64, we will simply ignore the upper word - * for CM2. - */ - u64 cm_error; - unsigned long revision, cm_addr, cm_other; - int ocause, cause, cm_error_cause_sft; + u64 cm_error, cm_addr, cm_other; + unsigned long revision; + int ocause, cause; char buf[256]; if (!mips_cm_present()) return; revision = mips_cm_revision(); - cm_error = read_gcr_error_cause(); - cm_addr = read_gcr_error_addr(); - cm_other = read_gcr_error_mult(); - cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF + - ((revision >= CM_REV_CM3) ? 31 : 0); - cause = cm_error >> cm_error_cause_sft; - - if (!cause) - /* All good */ - return; - - ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF; if (revision < CM_REV_CM3) { /* CM2 */ + cm_error = read_gcr_error_cause(); + cm_addr = read_gcr_error_addr(); + cm_other = read_gcr_error_mult(); + cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF; + ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF; + + if (!cause) + return; + if (cause < 16) { unsigned long cca_bits = (cm_error >> 15) & 7; unsigned long tr_bits = (cm_error >> 12) & 7; @@ -313,18 +303,30 @@ void mips_cm_error_report(void) } pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error, cm2_causes[cause], buf); - pr_err("CM_ADDR =%08lx\n", cm_addr); - pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]); + pr_err("CM_ADDR =%08llx\n", cm_addr); + pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]); } else { /* CM3 */ - /* Used by cause == {1,2,3} */ - unsigned long core_id_bits = (cm_error >> 22) & 0xf; - unsigned long vp_id_bits = (cm_error >> 18) & 0xf; - unsigned long cmd_bits = (cm_error >> 14) & 0xf; - unsigned long cmd_group_bits = (cm_error >> 11) & 0xf; - unsigned long cm3_cca_bits = (cm_error >> 8) & 7; - unsigned long mcp_bits = (cm_error >> 5) & 0xf; - unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf; - unsigned long sched_bit = cm_error & 0x1; + ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits; + ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit; + + cm_error = read64_gcr_error_cause(); + cm_addr = read64_gcr_error_addr(); + cm_other = read64_gcr_error_mult(); + cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF; + ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF; + + if (!cause) + return; + + /* Used by cause == {1,2,3} */ + core_id_bits = (cm_error >> 22) & 0xf; + vp_id_bits = (cm_error >> 18) & 0xf; + cmd_bits = (cm_error >> 14) & 0xf; + cmd_group_bits = (cm_error >> 11) & 0xf; + cm3_cca_bits = (cm_error >> 8) & 7; + mcp_bits = (cm_error >> 5) & 0xf; + cm3_tr_bits = (cm_error >> 1) & 0xf; + sched_bit = cm_error & 0x1; if (cause == 1 || cause == 3) { /* Tag ECC */ unsigned long tag_ecc = (cm_error >> 57) & 0x1; @@ -372,8 +374,8 @@ void mips_cm_error_report(void) pr_err("CM_ERROR=%llx %s <%s>\n", cm_error, cm3_causes[cause], buf); - pr_err("CM_ADDR =%lx\n", cm_addr); - pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]); + pr_err("CM_ADDR =%llx\n", cm_addr); + pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]); } /* reprime cause register */ From b85ff244533fb4b88f34bcca55c194f142338c3f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:09 -0700 Subject: [PATCH 018/120] MIPS: CPS: Set Status.BEV bit during early boot Set the Status.BEV bit throughout the early startup of a secondary core such that if an exception occurs the core branches to one of the exception vector entries from cps-vec.S, rather than branching to whatever is set in EBase. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11200/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 209ded16806b..b3fdb2a6405e 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -71,7 +71,7 @@ not_nmi: mtc0 t0, CP0_CAUSE /* Setup Status */ - li t0, ST0_CU1 | ST0_CU0 + li t0, ST0_CU1 | ST0_CU0 | ST0_BEV mtc0 t0, CP0_STATUS /* From 8fe2c5478b11d407e3c19d96eb9c0bfe19ce5f8c Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:10 -0700 Subject: [PATCH 019/120] MIPS: CPS: Set Status.KX on entry for MIPS64 kernels If the kernel may make use of 64 bit addresses outside of the compatibility address space then we need to set KX such that those accesses can succeed. Do so for MIPS64 kernels. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11201/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index b3fdb2a6405e..f2663e460d37 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -25,6 +25,12 @@ .set noreorder +#ifdef CONFIG_64BIT +# define STATUS_BITDEPS ST0_KX +#else +# define STATUS_BITDEPS 0 +#endif + /* * Set dest to non-zero if the core supports the MT ASE, else zero. If * MT is not supported then branch to nomt. @@ -71,7 +77,7 @@ not_nmi: mtc0 t0, CP0_CAUSE /* Setup Status */ - li t0, ST0_CU1 | ST0_CU0 | ST0_BEV + li t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS mtc0 t0, CP0_STATUS /* From 4e7d30dba493b60a80e9b590add1b4402265cc83 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 25 Oct 2015 23:21:42 +0100 Subject: [PATCH 020/120] MIPS: lantiq: add clk_round_rate() This adds a basic implementation of clk_round_rate() The clk_round_rate() function is called by multiple drivers and subsystems now and the lantiq clk driver is supposed to export this, but doesn't do so, this causes linking problems like this one: ERROR: "clk_round_rate" [drivers/media/v4l2-core/videodev.ko] undefined! Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: # 4.1+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11358/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/clk.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index 3fc2e6d70c77..a0706fd4ce0a 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -99,6 +99,23 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(clk_set_rate); +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(!clk_good(clk))) + return 0; + if (clk->rates && *clk->rates) { + unsigned long *r = clk->rates; + + while (*r && (*r != rate)) + r++; + if (!*r) { + return clk->rate; + } + } + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + int clk_enable(struct clk *clk) { if (unlikely(!clk_good(clk))) From 1b4a5ddb127caf125e14551ebd334be1acf21805 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 6 Oct 2015 15:12:05 +0100 Subject: [PATCH 021/120] MIPS: CDMM: Add builtin_mips_cdmm_driver() macro Add helper macro builtin_mips_cdmm_driver() for builtin CDMM drivers that don't do anything special in init and have no exit. The module_mips_cdmm_driver() helper isn't really appropriate for drivers that can't be built as a module. Signed-off-by: James Hogan Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linux-mips@linux-mips.org Cc: # 4.2.x- Patchwork: http://patchwork.linux-mips.org/patch/11264/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cdmm.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/mips/include/asm/cdmm.h b/arch/mips/include/asm/cdmm.h index bece2064cc8c..c06dbf8ba937 100644 --- a/arch/mips/include/asm/cdmm.h +++ b/arch/mips/include/asm/cdmm.h @@ -84,6 +84,17 @@ void mips_cdmm_driver_unregister(struct mips_cdmm_driver *); module_driver(__mips_cdmm_driver, mips_cdmm_driver_register, \ mips_cdmm_driver_unregister) +/* + * builtin_mips_cdmm_driver() - Helper macro for drivers that don't do anything + * special in init and have no exit. This eliminates some boilerplate. Each + * driver may only use this macro once, and calling it replaces device_initcall + * (or in some cases, the legacy __initcall). This is meant to be a direct + * parallel of module_mips_cdmm_driver() above but without the __exit stuff that + * is not used for builtin cases. + */ +#define builtin_mips_cdmm_driver(__mips_cdmm_driver) \ + builtin_driver(__mips_cdmm_driver, mips_cdmm_driver_register) + /* drivers/tty/mips_ejtag_fdc.c */ #ifdef CONFIG_MIPS_EJTAG_FDC_EARLYCON From 7963b3f127a7486815bc10639630c95c2792b811 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Mon, 19 Oct 2015 11:49:52 -0700 Subject: [PATCH 022/120] MIPS: add nmi_enter() + nmi_exit() to nmi_exception_handler() We need to enter NMI context when NMI interrupt fires. Signed-off-by: Petri Gynther Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11323/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fdb392b27e81..efcedd43780f 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1856,12 +1856,14 @@ void __noreturn nmi_exception_handler(struct pt_regs *regs) { char str[100]; + nmi_enter(); raw_notifier_call_chain(&nmi_chain, 0, regs); bust_spinlocks(1); snprintf(str, 100, "CPU%d NMI taken, CP0_EPC=%lx\n", smp_processor_id(), regs->cp0_epc); regs->cp0_epc = read_c0_errorepc(); die(str, regs); + nmi_exit(); } #define VECTORSPACING 0x100 /* for EI/VI mode */ From adaa0b6c49795551b07576e952dfa94c3ccded51 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Mon, 19 Oct 2015 11:44:24 -0700 Subject: [PATCH 023/120] MIPS: Switch BMIPS5000 to use r4k_wait_irqoff() BCM7425 CPU Interface Zephyr Processor, pages 5-309 and 5-310 BCM7428B0 CPU Interface Zephyr Processor, pages 5-337 and 5-338 WAIT instruction: Thread enters wait state. No instructions are executed until an interrupt occurs. The processor's clocks are stopped if both threads are in idle mode. Description: Execution of this instruction puts the thread into wait state, an idle mode in which no instructions are fetched or executed. The thread remains in wait state until an interrupt occurs that is not masked by the interrupt mask field in the Status register. Then, if interrupts are enabled by the IE bit in the Status register, the interrupt is serviced. The ERET instruction returns to the instruction following the WAIT instruction. If interrupts are disabled, the processor resumes executing instructions with the next sequential instruction. Programming notes: The WAIT instruction should be executed while interrupts are disabled by the IE bit in the Status register. This avoids a potential timing hazard, which occurs if an interrupt is taken between testing the counter and executing the WAIT instruction. In this hazard case, the interrupt will have been completed before the WAIT instruction is executed, so the processor will remain indefinitely in wait state until the next interrupt. Signed-off-by: Petri Gynther Reviewed-by: Florian Fainelli Cc: cernekee@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11322/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/idle.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index ab1478d5a4db..d636c70fef19 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -160,7 +160,6 @@ void __init check_wait(void) case CPU_BMIPS3300: case CPU_BMIPS4350: case CPU_BMIPS4380: - case CPU_BMIPS5000: case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: @@ -171,7 +170,9 @@ void __init check_wait(void) case CPU_XLP: cpu_wait = r4k_wait; break; - + case CPU_BMIPS5000: + cpu_wait = r4k_wait_irqoff; + break; case CPU_RM7000: cpu_wait = rm7k_wait_irqoff; break; From 61379878320664ed44901b0537254e983fc7e4c4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 30 Oct 2015 00:54:47 +0200 Subject: [PATCH 024/120] MIPS: vmlinux: discard .MIPS.abiflags Discard .MIPS.abiflags from vmlinux. It's not needed and will cause issues e.g. with old OCTEON bootloaders that cannot tolerate additional program headers. Before the patch: $ readelf --program-headers octeon-vmlinux Elf file type is EXEC (Executable file) Entry point 0xffffffff815d09d0 There are 3 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align ABIFLAGS 0x00000000005e77f0 0xffffffff816e67f0 0xffffffff816e67f0 0x0000000000000018 0x0000000000000018 R 8 LOAD 0x0000000000001000 0xffffffff81100000 0xffffffff81100000 0x0000000000b57f80 0x0000000001b86360 RWE 1000 NOTE 0x00000000004e02e0 0xffffffff815df2e0 0xffffffff815df2e0 0x0000000000000024 0x0000000000000024 R 4 After the patch: $ readelf --program-headers octeon-vmlinux Elf file type is EXEC (Executable file) Entry point 0xffffffff815d09d0 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000001000 0xffffffff81100000 0xffffffff81100000 0x0000000000b57f80 0x0000000001b86360 RWE 1000 NOTE 0x00000000004e02e0 0xffffffff815df2e0 0xffffffff815df2e0 0x0000000000000024 0x0000000000000024 R 4 Suggested-by: Matthew Fortune Suggested-by: Ralf Baechle Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/11402/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 07d32a4aea60..06632d69ee5a 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -181,6 +181,7 @@ SECTIONS DISCARDS /DISCARD/ : { /* ABI crap starts here */ + *(.MIPS.abiflags) *(.MIPS.options) *(.options) *(.pdr) From 3bfb7224566593219dbd67474dacb23ef7c080e3 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 30 Oct 2015 00:54:48 +0200 Subject: [PATCH 025/120] MIPS: OCTEON: omit ELF NOTE segments OCTEON Pre-SDK-1.8.1 bootloaders can not handle PT_NOTE program headers, so do not emit them. Before the patch: $ readelf --program-headers octeon-vmlinux Elf file type is EXEC (Executable file) Entry point 0xffffffff815d09d0 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000001000 0xffffffff81100000 0xffffffff81100000 0x0000000000b57f80 0x0000000001b86360 RWE 1000 NOTE 0x00000000004e02e0 0xffffffff815df2e0 0xffffffff815df2e0 0x0000000000000024 0x0000000000000024 R 4 After the patch: $ readelf --program-headers octeon-vmlinux Elf file type is EXEC (Executable file) Entry point 0xffffffff815d09d0 There are 1 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000001000 0xffffffff81100000 0xffffffff81100000 0x0000000000b57f80 0x0000000001b86360 RWE 1000 The patch was tested on DSR-1000N router. Signed-off-by: David Daney Signed-off-by: Aaro Koskinen Cc: Matthew Fortune Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11403/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 06632d69ee5a..cce2fcb58881 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -17,7 +17,9 @@ OUTPUT_ARCH(mips) ENTRY(kernel_entry) PHDRS { text PT_LOAD FLAGS(7); /* RWX */ +#ifndef CONFIG_CAVIUM_OCTEON_SOC note PT_NOTE FLAGS(4); /* R__ */ +#endif /* CAVIUM_OCTEON_SOC */ } #ifdef CONFIG_32BIT @@ -71,7 +73,12 @@ SECTIONS __stop___dbe_table = .; } - NOTES :text :note +#ifdef CONFIG_CAVIUM_OCTEON_SOC +#define NOTES_HEADER +#else /* CONFIG_CAVIUM_OCTEON_SOC */ +#define NOTES_HEADER :note +#endif /* CONFIG_CAVIUM_OCTEON_SOC */ + NOTES :text NOTES_HEADER .dummy : { *(.dummy) } :text _sdata = .; /* Start of data section */ From 195cee92afcb20b2156437e98b144d94812e4afd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 10 Nov 2015 17:06:37 +0000 Subject: [PATCH 026/120] MIPS: Fix duplicate CP0_* definitions. Remove the definition in locore.S and move a few of the other similar definitions in asm/mipsregs.h too. CP0_INTCTL, CP0_SRSCTL, & CP0_SRSMAP are unused so they're just dropped instead. CP0_DDATA_LO is left where it is as I have patches to eliminate its use in locore.S and it otherwise is unlikely to need to be used from assembly code. Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Paul Burton Cc: Paolo Bonzini Cc: Gleb Natapov Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11461/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 3 +++ arch/mips/kvm/locore.S | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index c64781cf649f..f935e15adcc6 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -50,6 +50,7 @@ #define CP0_PAGEMASK $5 #define CP0_WIRED $6 #define CP0_INFO $7 +#define CP0_HWRENA $7, 0 #define CP0_BADVADDR $8 #define CP0_COUNT $9 #define CP0_ENTRYHI $10 @@ -59,6 +60,8 @@ #define CP0_EPC $14 #define CP0_PRID $15 #define CP0_CONFIG $16 +#define CP0_CONFIG3 $16, 3 +#define CP0_CONFIG5 $16, 5 #define CP0_LLADDR $17 #define CP0_WATCHLO $18 #define CP0_WATCHHI $19 diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index c567240386a0..7bab3a4e8f7d 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -36,14 +36,6 @@ #define PT_HOST_USERLOCAL PT_EPC #define CP0_DDATA_LO $28,3 -#define CP0_CONFIG3 $16,3 -#define CP0_CONFIG5 $16,5 -#define CP0_EBASE $15,1 - -#define CP0_INTCTL $12,1 -#define CP0_SRSCTL $12,2 -#define CP0_SRSMAP $12,3 -#define CP0_HWRENA $7,0 /* Resume Flags */ #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ From 609cf6f2291a69d09aa5c02d74cd4488b19aa9a6 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:11 -0700 Subject: [PATCH 027/120] MIPS: CPS: Early debug using an ns16550-compatible UART Provide support for outputting early debug information, in the form of various register values should an exception occur, during the early bringup of secondary cores. This code requires an ns16550-compatible UART accessible from the secondary core, and is written in assembly due to the environment in which such early exceptions occur where way may not have a stack, be coherent or even have initialised caches. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Andrew Bresticker Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: Jason Cooper Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11202/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig.debug | 26 ++++ arch/mips/include/asm/mipsregs.h | 3 + arch/mips/kernel/Makefile | 1 + arch/mips/kernel/cps-vec-ns16550.S | 202 +++++++++++++++++++++++++++++ arch/mips/kernel/cps-vec.S | 20 +++ 5 files changed, 252 insertions(+) create mode 100644 arch/mips/kernel/cps-vec-ns16550.S diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index b43e288ec567..f0e314ceb8ba 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -159,4 +159,30 @@ config SCACHE_DEBUGFS If unsure, say N. +menuconfig MIPS_CPS_NS16550 + bool "CPS SMP NS16550 UART output" + depends on MIPS_CPS + help + Output debug information via an ns16550 compatible UART if exceptions + occur early in the boot process of a secondary core. + +if MIPS_CPS_NS16550 + +config MIPS_CPS_NS16550_BASE + hex "UART Base Address" + default 0x1b0003f8 if MIPS_MALTA + help + The base address of the ns16550 compatible UART on which to output + debug information from the early stages of core startup. + +config MIPS_CPS_NS16550_SHIFT + int "UART Register Shift" + default 0 if MIPS_MALTA + help + The number of bits to shift ns16550 register indices by in order to + form their addresses. That is, log base 2 of the span between + adjacent ns16550 registers in the system. + +endif # MIPS_CPS_NS16550 + endmenu diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index f935e15adcc6..69f8ec548eac 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -52,6 +52,7 @@ #define CP0_INFO $7 #define CP0_HWRENA $7, 0 #define CP0_BADVADDR $8 +#define CP0_BADINSTR $8, 1 #define CP0_COUNT $9 #define CP0_ENTRYHI $10 #define CP0_COMPARE $11 @@ -59,6 +60,8 @@ #define CP0_CAUSE $13 #define CP0_EPC $14 #define CP0_PRID $15 +#define CP0_EBASE $15, 1 +#define CP0_CMGCRBASE $15, 3 #define CP0_CONFIG $16 #define CP0_CONFIG3 $16, 3 #define CP0_CONFIG5 $16, 5 diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index d982be1ea1c3..68e2b7db9348 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o obj-$(CONFIG_MIPS_CMP) += smp-cmp.o obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o +obj-$(CONFIG_MIPS_CPS_NS16550) += cps-vec-ns16550.o obj-$(CONFIG_MIPS_GIC_IPI) += smp-gic.o obj-$(CONFIG_MIPS_SPRAM) += spram.o diff --git a/arch/mips/kernel/cps-vec-ns16550.S b/arch/mips/kernel/cps-vec-ns16550.S new file mode 100644 index 000000000000..6d246ad05638 --- /dev/null +++ b/arch/mips/kernel/cps-vec-ns16550.S @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Paul Burton + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#define UART_TX_OFS (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT) +#define UART_LSR_OFS (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT) + +/** + * _mips_cps_putc() - write a character to the UART + * @a0: ASCII character to write + * @t9: UART base address + */ +LEAF(_mips_cps_putc) +1: lw t0, UART_LSR_OFS(t9) + andi t0, t0, UART_LSR_TEMT + beqz t0, 1b + sb a0, UART_TX_OFS(t9) + jr ra + END(_mips_cps_putc) + +/** + * _mips_cps_puts() - write a string to the UART + * @a0: pointer to NULL-terminated ASCII string + * @t9: UART base address + * + * Write a null-terminated ASCII string to the UART. + */ +NESTED(_mips_cps_puts, 0, ra) + move s7, ra + move s6, a0 + +1: lb a0, 0(s6) + beqz a0, 2f + jal _mips_cps_putc + PTR_ADDIU s6, s6, 1 + b 1b + +2: jr s7 + END(_mips_cps_puts) + +/** + * _mips_cps_putx4 - write a 4b hex value to the UART + * @a0: the 4b value to write to the UART + * @t9: UART base address + * + * Write a single hexadecimal character to the UART. + */ +NESTED(_mips_cps_putx4, 0, ra) + andi a0, a0, 0xf + li t0, '0' + blt a0, 10, 1f + li t0, 'a' + addiu a0, a0, -10 +1: addu a0, a0, t0 + b _mips_cps_putc + END(_mips_cps_putx4) + +/** + * _mips_cps_putx8 - write an 8b hex value to the UART + * @a0: the 8b value to write to the UART + * @t9: UART base address + * + * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART. + */ +NESTED(_mips_cps_putx8, 0, ra) + move s3, ra + move s2, a0 + srl a0, a0, 4 + jal _mips_cps_putx4 + move a0, s2 + move ra, s3 + b _mips_cps_putx4 + END(_mips_cps_putx8) + +/** + * _mips_cps_putx16 - write a 16b hex value to the UART + * @a0: the 16b value to write to the UART + * @t9: UART base address + * + * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART. + */ +NESTED(_mips_cps_putx16, 0, ra) + move s5, ra + move s4, a0 + srl a0, a0, 8 + jal _mips_cps_putx8 + move a0, s4 + move ra, s5 + b _mips_cps_putx8 + END(_mips_cps_putx16) + +/** + * _mips_cps_putx32 - write a 32b hex value to the UART + * @a0: the 32b value to write to the UART + * @t9: UART base address + * + * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART. + */ +NESTED(_mips_cps_putx32, 0, ra) + move s7, ra + move s6, a0 + srl a0, a0, 16 + jal _mips_cps_putx16 + move a0, s6 + move ra, s7 + b _mips_cps_putx16 + END(_mips_cps_putx32) + +#ifdef CONFIG_64BIT + +/** + * _mips_cps_putx64 - write a 64b hex value to the UART + * @a0: the 64b value to write to the UART + * @t9: UART base address + * + * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART. + */ +NESTED(_mips_cps_putx64, 0, ra) + move sp, ra + move s8, a0 + dsrl32 a0, a0, 0 + jal _mips_cps_putx32 + move a0, s8 + move ra, sp + b _mips_cps_putx32 + END(_mips_cps_putx64) + +#define _mips_cps_putxlong _mips_cps_putx64 + +#else /* !CONFIG_64BIT */ + +#define _mips_cps_putxlong _mips_cps_putx32 + +#endif /* !CONFIG_64BIT */ + +/** + * mips_cps_bev_dump() - dump relevant exception state to UART + * @a0: pointer to NULL-terminated ASCII string naming the exception + * + * Write information that may be useful in debugging an exception to the + * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception + * will only be run if something goes horribly wrong very early during + * the bringup of a core and it is very likely to be unsafe to perform + * memory accesses at that point (cache state indeterminate, EVA may not + * be configured, coherence may be disabled) let alone have a stack, + * this is all written in assembly using only registers & unmapped + * uncached access to the UART registers. + */ +LEAF(mips_cps_bev_dump) + move s0, ra + move s1, a0 + + li t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE) + + PTR_LA a0, str_newline + jal _mips_cps_puts + PTR_LA a0, str_bev + jal _mips_cps_puts + move a0, s1 + jal _mips_cps_puts + PTR_LA a0, str_newline + jal _mips_cps_puts + PTR_LA a0, str_newline + jal _mips_cps_puts + +#define DUMP_COP0_REG(reg, name, sz, _mfc0) \ + PTR_LA a0, 8f; \ + jal _mips_cps_puts; \ + _mfc0 a0, reg; \ + jal _mips_cps_putx##sz; \ + PTR_LA a0, str_newline; \ + jal _mips_cps_puts; \ + TEXT(name) + + DUMP_COP0_REG(CP0_CAUSE, "Cause: 0x", 32, mfc0) + DUMP_COP0_REG(CP0_STATUS, "Status: 0x", 32, mfc0) + DUMP_COP0_REG(CP0_EBASE, "EBase: 0x", long, MFC0) + DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0) + DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0) + + PTR_LA a0, str_newline + jal _mips_cps_puts + jr s0 + END(mips_cps_bev_dump) + +.pushsection .data +str_bev: .asciiz "BEV Exception: " +str_newline: .asciiz "\r\n" +.popsection diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index f2663e460d37..b242ae3eb466 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -31,6 +31,20 @@ # define STATUS_BITDEPS 0 #endif +#ifdef CONFIG_MIPS_CPS_NS16550 + +#define DUMP_EXCEP(name) \ + PTR_LA a0, 8f; \ + jal mips_cps_bev_dump; \ + nop; \ + TEXT(name) + +#else /* !CONFIG_MIPS_CPS_NS16550 */ + +#define DUMP_EXCEP(name) + +#endif /* !CONFIG_MIPS_CPS_NS16550 */ + /* * Set dest to non-zero if the core supports the MT ASE, else zero. If * MT is not supported then branch to nomt. @@ -194,36 +208,42 @@ dcache_done: .org 0x200 LEAF(excep_tlbfill) + DUMP_EXCEP("TLB Fill") b . nop END(excep_tlbfill) .org 0x280 LEAF(excep_xtlbfill) + DUMP_EXCEP("XTLB Fill") b . nop END(excep_xtlbfill) .org 0x300 LEAF(excep_cache) + DUMP_EXCEP("Cache") b . nop END(excep_cache) .org 0x380 LEAF(excep_genex) + DUMP_EXCEP("General") b . nop END(excep_genex) .org 0x400 LEAF(excep_intex) + DUMP_EXCEP("Interrupt") b . nop END(excep_intex) .org 0x480 LEAF(excep_ejtag) + DUMP_EXCEP("EJTAG") PTR_LA k0, ejtag_debug_handler jr k0 nop From 946db17349f6922a9c8a959c34ad9fb3aa238952 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:12 -0700 Subject: [PATCH 028/120] MIPS: CPS: Read CM GCR base from cop0 Rather than patching the start of mips_cps_core_entry to provide the base address of the CM GCRs, simply read that base address from the cop0 CMGCRBase register, converting from the physical address to an uncached virtual address. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Rusty Russell Cc: Andrew Bresticker Cc: linux-kernel@vger.kernel.org Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11203/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 12 ++++++++---- arch/mips/kernel/smp-cps.c | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index b242ae3eb466..2164dc4deace 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -67,11 +67,9 @@ LEAF(mips_cps_core_entry) /* - * These first 12 bytes will be patched by cps_smp_setup to load the - * base address of the CM GCRs into register v1 and the CCA to use into - * register s0. + * These first 4 bytes will be patched by cps_smp_setup to load the + * CCA to use into register s0. */ - .quad 0 .word 0 /* Check whether we're here due to an NMI */ @@ -171,6 +169,12 @@ dcache_done: 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 */ li t0, 0xff sw t0, GCR_CL_COHERENCE_OFS(v1) diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index c88937745b4e..8b967507e852 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -133,11 +133,9 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) /* * Patch the start of mips_cps_core_entry to provide: * - * v1 = CM base address * s0 = kseg0 CCA */ entry_code = (u32 *)&mips_cps_core_entry; - UASM_i_LA(&entry_code, 3, (long)mips_cm_base); uasm_i_addiu(&entry_code, 16, 0, cca); blast_dcache_range((unsigned long)&mips_cps_core_entry, (unsigned long)entry_code); From 192fbc20258c79e3f776a5ce6cea4654376f5af6 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:13 -0700 Subject: [PATCH 029/120] MIPS: CPS: Skip Config1 presence check The Config1 register is architecturally defined as required, and is thus present in all systems which may make use of cps-vec.S. Skip the check for its presence via the Config.M bit. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11204/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cps-vec.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 2164dc4deace..8fd5a276cad2 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -50,9 +50,7 @@ * MT is not supported then branch to nomt. */ .macro has_mt dest, nomt - mfc0 \dest, CP0_CONFIG - bgez \dest, \nomt - mfc0 \dest, CP0_CONFIG, 1 + mfc0 \dest, CP0_CONFIG, 1 bgez \dest, \nomt mfc0 \dest, CP0_CONFIG, 2 bgez \dest, \nomt From a8c20614b0163a71f2df3f9788bfe8b9ff07d742 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:14 -0700 Subject: [PATCH 030/120] MIPS: CPS: Warn if a core doesn't start When debugging core bringup it is useful to see the state of the CPC sequencer, so output that value if the core hasn't started within a reasonable amount of time (1 second). This avoids simply appearing to the user to hang if a secondary core fails to start. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Rusty Russell Cc: Andrew Bresticker Cc: linux-kernel@vger.kernel.org Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11205/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-cps.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 8b967507e852..48b1b7554f05 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -8,6 +8,7 @@ * option) any later version. */ +#include #include #include #include @@ -188,7 +189,8 @@ err_out: static void boot_core(unsigned core) { - u32 access; + u32 access, stat, seq_state; + unsigned timeout; /* Select the appropriate core */ write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); @@ -208,6 +210,28 @@ static void boot_core(unsigned core) /* Reset the core */ mips_cpc_lock_other(core); write_cpc_co_cmd(CPC_Cx_CMD_RESET); + + timeout = 100; + while (true) { + stat = read_cpc_co_stat_conf(); + seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE_MSK; + + /* U6 == coherent execution, ie. the core is up */ + if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U6) + break; + + /* Delay a little while before we start warning */ + if (timeout) { + timeout--; + mdelay(10); + continue; + } + + pr_warn("Waiting for core %u to start... STAT_CONF=0x%x\n", + core, stat); + mdelay(1000); + } + mips_cpc_unlock_other(); } else { /* Take the core out of reset */ From 252d6aa605fa05b559347d3ed0a4f11bbdf6d3d0 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:15 -0700 Subject: [PATCH 031/120] MIPS: CM: Fix GCR_Cx_CONFIG PVPE mask The PVPE (or PVP in >= CM3) field is 10 bits wide, but the mask previously only covered the bottom 9 bits. Extend the mask to cover all 10 bits of the field. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11206/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 9261c003990a..7740c4f44289 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -359,7 +359,7 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_Cx_CONFIG_IOCUTYPE_SHF 10 #define CM_GCR_Cx_CONFIG_IOCUTYPE_MSK (_ULCAST_(0x3) << 10) #define CM_GCR_Cx_CONFIG_PVPE_SHF 0 -#define CM_GCR_Cx_CONFIG_PVPE_MSK (_ULCAST_(0x1ff) << 0) +#define CM_GCR_Cx_CONFIG_PVPE_MSK (_ULCAST_(0x3ff) << 0) /* GCR_Cx_OTHER register fields */ #define CM_GCR_Cx_OTHER_CORENUM_SHF 16 From 23d5de8efb9aed48074a72bf3d43841e1556ca42 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:16 -0700 Subject: [PATCH 032/120] MIPS: CM: Introduce core-other locking functions Introduce mips_cm_lock_other & mips_cm_unlock_other, mirroring the existing CPC equivalents, in order to lock access from the current core to another via the core-other GCR region. This hasn't been required in the past but with CM3 the CPC starts using GCR_CL_OTHER rather than CPC_CL_OTHER and this will be required for safety. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11207/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 32 +++++++++++++++++++++++++++ arch/mips/kernel/mips-cm.c | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 7740c4f44289..6516e9da5133 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -364,6 +364,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) /* GCR_Cx_OTHER register fields */ #define CM_GCR_Cx_OTHER_CORENUM_SHF 16 #define CM_GCR_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xffff) << 16) +#define CM3_GCR_Cx_OTHER_CORE_SHF 8 +#define CM3_GCR_Cx_OTHER_CORE_MSK (_ULCAST_(0x3f) << 8) +#define CM3_GCR_Cx_OTHER_VP_SHF 0 +#define CM3_GCR_Cx_OTHER_VP_MSK (_ULCAST_(0x7) << 0) /* GCR_Cx_RESET_BASE register fields */ #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF 12 @@ -474,4 +478,32 @@ static inline unsigned int mips_cm_vp_id(unsigned int cpu) return (core * mips_cm_max_vp_width()) + vp; } +#ifdef CONFIG_MIPS_CM + +/** + * mips_cm_lock_other - lock access to another core + * @core: the other core to be accessed + * @vp: the VP within the other core to be accessed + * + * Call before operating upon a core via the 'other' register region in + * order to prevent the region being moved during access. Must be followed + * by a call to mips_cm_unlock_other. + */ +extern void mips_cm_lock_other(unsigned int core, unsigned int vp); + +/** + * mips_cm_unlock_other - unlock access to another core + * + * Call after operating upon another core via the 'other' register region. + * Must be called after mips_cm_lock_other. + */ +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_unlock_other(void) { } + +#endif /* !CONFIG_MIPS_CM */ + #endif /* __MIPS_ASM_MIPS_CM_H__ */ diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 02f7d7a41133..01908dbdf677 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include #include @@ -136,6 +138,9 @@ static char *cm3_causes[32] = { "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f" }; +static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock); +static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags); + phys_addr_t __mips_cm_phys_base(void) { u32 config3 = read_c0_config3(); @@ -200,6 +205,7 @@ int mips_cm_probe(void) { phys_addr_t addr; u32 base_reg; + unsigned cpu; /* * No need to probe again if we have already been @@ -247,9 +253,42 @@ int mips_cm_probe(void) /* determine register width for this CM */ mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3); + for_each_possible_cpu(cpu) + spin_lock_init(&per_cpu(cm_core_lock, cpu)); + return 0; } +void mips_cm_lock_other(unsigned int core, unsigned int vp) +{ + unsigned curr_core; + u32 val; + + preempt_disable(); + curr_core = current_cpu_data.core; + spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), + per_cpu(cm_core_lock_flags, curr_core)); + + if (mips_cm_revision() >= CM_REV_CM3) { + val = core << CM3_GCR_Cx_OTHER_CORE_SHF; + val |= vp << CM3_GCR_Cx_OTHER_VP_SHF; + } else { + BUG_ON(vp != 0); + val = core << CM_GCR_Cx_OTHER_CORENUM_SHF; + } + + write_gcr_cl_other(val); +} + +void mips_cm_unlock_other(void) +{ + unsigned curr_core = current_cpu_data.core; + + spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core), + per_cpu(cm_core_lock_flags, curr_core)); + preempt_enable(); +} + void mips_cm_error_report(void) { u64 cm_error, cm_addr, cm_other; From 4ede31617056b7424eef28dce59dd6dbe81729c3 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:17 -0700 Subject: [PATCH 033/120] MIPS: CM: make use of mips_cm_{lock,unlock}_other Document that CPC core-other accesses must take place within the bounds of the CM lock, and begin using the CM lock functions where we access the GCRs of other cores. This is required because with CM3 the CPC began using GCR_CL_OTHER instead of CPC_CL_OTHER. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Rusty Russell Cc: Andrew Bresticker Cc: Bjorn Helgaas Cc: linux-kernel@vger.kernel.org Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11208/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cpc.h | 3 ++- arch/mips/kernel/smp-cps.c | 7 +++++-- arch/mips/kernel/smp-gic.c | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index f386f32702f1..e09035239e53 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h @@ -149,7 +149,8 @@ BUILD_CPC_Cx_RW(other, 0x10) * core: the other core to be accessed * * Call before operating upon a core via the 'other' register region in - * order to prevent the region being moved during access. Must be followed + * order to prevent the region being moved during access. Must be called + * within the bounds of a mips_cm_{lock,unlock}_other pair, and followed * by a call to mips_cpc_unlock_other. */ extern void mips_cpc_lock_other(unsigned int core); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 48b1b7554f05..e04c8057b882 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -38,8 +38,9 @@ static unsigned core_vpe_count(unsigned core) if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) return 1; - write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); + mips_cm_lock_other(core, 0); cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK; + mips_cm_unlock_other(); return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1; } @@ -193,7 +194,7 @@ static void boot_core(unsigned core) unsigned timeout; /* Select the appropriate core */ - write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); + mips_cm_lock_other(core, 0); /* Set its reset vector */ write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry)); @@ -238,6 +239,8 @@ static void boot_core(unsigned core) write_gcr_co_reset_release(0); } + mips_cm_unlock_other(); + /* The core is now powered up */ bitmap_set(core_power, core, 1); } diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c index 5f0ab5bcd01e..9b63829cf929 100644 --- a/arch/mips/kernel/smp-gic.c +++ b/arch/mips/kernel/smp-gic.c @@ -46,9 +46,11 @@ void gic_send_ipi_single(int cpu, unsigned int action) if (mips_cpc_present() && (core != current_cpu_data.core)) { while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) { + mips_cm_lock_other(core, 0); mips_cpc_lock_other(core); write_cpc_co_cmd(CPC_Cx_CMD_PWRUP); mips_cpc_unlock_other(); + mips_cm_unlock_other(); } } From 78a54c4d8e5a7915a4ec2ba0eb461fae50590683 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:12:18 -0700 Subject: [PATCH 034/120] MIPS: CM, CPC: Ensure core-other GCRs reflect the correct core Ensure the update to which core the core-other GCR regions reflect has taken place before any core-other GCRs are accessed by placing a memory barrier (sync instruction) between the write to the core-other registers and any such GCR accesses. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Bjorn Helgaas Cc: linux-kernel@vger.kernel.org Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11209/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-cm.c | 6 ++++++ arch/mips/kernel/mips-cpc.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 01908dbdf677..1448c1f43d4e 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -278,6 +278,12 @@ void mips_cm_lock_other(unsigned int core, unsigned int vp) } write_gcr_cl_other(val); + + /* + * Ensure the core-other region reflects the appropriate core & + * VP before any accesses to it occur. + */ + mb(); } void mips_cm_unlock_other(void) diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 8af4d627b68b..566b8d2c092c 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -76,6 +76,12 @@ void mips_cpc_lock_other(unsigned int core) spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core), per_cpu(cpc_core_lock_flags, curr_core)); write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF); + + /* + * Ensure the core-other region reflects the appropriate core & + * VP before any accesses to it occur. + */ + mb(); } void mips_cpc_unlock_other(void) From 5b10a0e84b4ebe02a7018846e882caa112b4ffc6 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:24:20 -0700 Subject: [PATCH 035/120] MIPS: Always use r4k_wait_irqoff for MIPSr6 Prior to release 6 of the MIPS architecture it has been implementation dependent whether masked interrupts cause a wait instruction to return, so the kernel has effectively had to maintain a whitelist of cores upon which it is safe to use the r4k_wait_irqoff cpu_wait implementation. With MIPSr6 this is no longer implementation dependent and r4k_wait_irqoff can always be used. Remove the existing I6400 case which will no longer ever be hit, and was incorrect anyway since I6400 & r6 in general doesn't have the WII bit. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11210/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/idle.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index ab1478d5a4db..3e2b0b6c3b08 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -134,6 +134,16 @@ void __init check_wait(void) return; } + /* + * MIPSr6 specifies that masked interrupts should unblock an executing + * wait instruction, and thus that it is safe for us to use + * r4k_wait_irqoff. Yippee! + */ + if (cpu_has_mips_r6) { + cpu_wait = r4k_wait_irqoff; + return; + } + switch (current_cpu_type()) { case CPU_R3081: case CPU_R3081E: @@ -196,7 +206,6 @@ void __init check_wait(void) case CPU_INTERAPTIV: case CPU_M5150: case CPU_QEMU_GENERIC: - case CPU_I6400: cpu_wait = r4k_wait; if (read_c0_config7() & MIPS_CONF7_WII) cpu_wait = r4k_wait_irqoff; From dbfd657ad12d872d04d5b105876669058285a166 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:48 -0700 Subject: [PATCH 036/120] MIPS: tlbex: Stop open-coding build_convert_pte_to_entrylo Make use of build_convert_pte_to_entrylo in the RIXI cases within build_update_entries rather than open-coding it 4 times. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11214/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 323d1d302f2b..0dd24b00e551 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1010,13 +1010,13 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) uasm_i_ld(p, tmp, 0, ptep); /* get even pte */ uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ if (cpu_has_rixi) { - UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); + build_convert_pte_to_entrylo(p, tmp); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); + build_convert_pte_to_entrylo(p, ptep); } else { - uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */ + build_convert_pte_to_entrylo(p, tmp); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */ + build_convert_pte_to_entrylo(p, ptep); } UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ } else { @@ -1050,17 +1050,17 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) if (r45k_bvahwbug()) build_tlb_probe_entry(p); if (cpu_has_rixi) { - UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); + build_convert_pte_to_entrylo(p, tmp); if (r4k_250MHZhwbug()) UASM_i_MTC0(p, 0, C0_ENTRYLO0); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); + build_convert_pte_to_entrylo(p, ptep); } else { - UASM_i_SRL(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */ + build_convert_pte_to_entrylo(p, tmp); if (r4k_250MHZhwbug()) UASM_i_MTC0(p, 0, C0_ENTRYLO0); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - UASM_i_SRL(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */ + build_convert_pte_to_entrylo(p, ptep); if (r45k_bvahwbug()) uasm_i_mfc0(p, tmp, C0_INDEX); } From 974a0b6a2c40260b0ac64a5523106f5991cc5127 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:49 -0700 Subject: [PATCH 037/120] MIPS: tlbex: Remove some RIXI redundancy The cpu_has_rixi cases in build_update_entries are now identical to the non-RIXI cases with the one exception of the r45k_bvahwbug case which is hardcoded as never happening anyway & presumably was either missed from the RIXI path or would never happen on a CPU with RIXI support. Remove the redundant checks & duplication. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11215/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 0dd24b00e551..ce5a0ecfeb21 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1009,15 +1009,9 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) if (cpu_has_64bits) { uasm_i_ld(p, tmp, 0, ptep); /* get even pte */ uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ - if (cpu_has_rixi) { - build_convert_pte_to_entrylo(p, tmp); - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - build_convert_pte_to_entrylo(p, ptep); - } else { - build_convert_pte_to_entrylo(p, tmp); - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - build_convert_pte_to_entrylo(p, ptep); - } + build_convert_pte_to_entrylo(p, tmp); + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ + build_convert_pte_to_entrylo(p, ptep); UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ } else { int pte_off_even = sizeof(pte_t) / 2; @@ -1049,21 +1043,13 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ if (r45k_bvahwbug()) build_tlb_probe_entry(p); - if (cpu_has_rixi) { - build_convert_pte_to_entrylo(p, tmp); - if (r4k_250MHZhwbug()) - UASM_i_MTC0(p, 0, C0_ENTRYLO0); - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - build_convert_pte_to_entrylo(p, ptep); - } else { - build_convert_pte_to_entrylo(p, tmp); - if (r4k_250MHZhwbug()) - UASM_i_MTC0(p, 0, C0_ENTRYLO0); - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - build_convert_pte_to_entrylo(p, ptep); - if (r45k_bvahwbug()) - uasm_i_mfc0(p, tmp, C0_INDEX); - } + build_convert_pte_to_entrylo(p, tmp); + if (r4k_250MHZhwbug()) + UASM_i_MTC0(p, 0, C0_ENTRYLO0); + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ + build_convert_pte_to_entrylo(p, ptep); + if (r45k_bvahwbug()) + uasm_i_mfc0(p, tmp, C0_INDEX); if (r4k_250MHZhwbug()) UASM_i_MTC0(p, 0, C0_ENTRYLO1); UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ From c676589b057a01dab418985f018123a634c1265c Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:50 -0700 Subject: [PATCH 038/120] MIPS: tlbex: Share MIPS32 32 bit phys & MIPS64 64 bit phys code The code in build_update_entries for 64 bit physical addresses on a MIPS64 CPU and 32 bit physical addresses on a MIPS32 CPU is now identical, with the exception of r4k bug workaround in the latter which would simply not apply to the former. Remove the duplication and some Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11216/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index ce5a0ecfeb21..bc829fc2421d 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1005,15 +1005,7 @@ 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. */ -#ifdef CONFIG_PHYS_ADDR_T_64BIT - if (cpu_has_64bits) { - uasm_i_ld(p, tmp, 0, ptep); /* get even pte */ - uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ - build_convert_pte_to_entrylo(p, tmp); - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - build_convert_pte_to_entrylo(p, ptep); - UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ - } else { + 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); #ifdef CONFIG_XPA @@ -1037,8 +1029,9 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) uasm_i_mthc0(p, tmp, C0_ENTRYLO0); uasm_i_mthc0(p, ptep, C0_ENTRYLO1); #endif + return; } -#else + UASM_i_LW(p, tmp, 0, ptep); /* get even pte */ UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ if (r45k_bvahwbug()) @@ -1053,7 +1046,6 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) if (r4k_250MHZhwbug()) UASM_i_MTC0(p, 0, C0_ENTRYLO1); UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ -#endif } struct mips_huge_tlb_info { From c6956728c76d35f2314dd54a74680360760cc2fd Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:51 -0700 Subject: [PATCH 039/120] MIPS: Tidy EntryLo bit definitions, add PFN Tidy up the definition of the EntryLo RI & XI bits using BITS_PER_LONG rather than #ifdef'ing on CONFIG_64BIT, and add a definition for the offset to the PFN field for use by a later patch. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Maciej W. Rozycki Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11217/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 69f8ec548eac..e43aca183c99 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -132,15 +132,9 @@ #define R3K_ENTRYLO_N (_ULCAST_(1) << 11) /* MIPS32/64 EntryLo bit definitions */ -#ifdef CONFIG_64BIT -/* as read by dmfc0 */ -#define MIPS_ENTRYLO_XI (_ULCAST_(1) << 62) -#define MIPS_ENTRYLO_RI (_ULCAST_(1) << 63) -#else -/* as read by mfc0 */ -#define MIPS_ENTRYLO_XI (_ULCAST_(1) << 30) -#define MIPS_ENTRYLO_RI (_ULCAST_(1) << 31) -#endif +#define MIPS_ENTRYLO_PFN_SHIFT 6 +#define MIPS_ENTRYLO_XI (_ULCAST_(1) << (BITS_PER_LONG - 2)) +#define MIPS_ENTRYLO_RI (_ULCAST_(1) << (BITS_PER_LONG - 1)) /* * Values for PageMask register From 00bf1c691d082c1945fdba032c03a9a82e9e7e61 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:52 -0700 Subject: [PATCH 040/120] MIPS: tlbex: Avoid placing software PTE bits in Entry* PFN fields Commit 748e787eb6de ("MIPS: Optimize TLB refill for RI/XI configurations.") stopped explicitly clearing the bits used by software in PTEs by making use of a rotate instruction that rotates them into the fill bits of the Entry{Lo,Hi} register. This can only work if there are actually enough fill bits in the register to cover the software maintained bits, otherwise we end up writing those bits into the upper bits of the PFN or PFNX field of the Entry{Lo,Hi} register. Fix this by detecting the number of fill bits present in the Entry{Lo,Hi} registers & explicitly clearing the software bits where necessary. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11218/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 47 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index bc829fc2421d..6b7cc20efd92 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -311,6 +311,7 @@ static struct uasm_label labels[128]; static struct uasm_reloc relocs[128]; static int check_for_high_segbits; +static bool fill_includes_sw_bits; static unsigned int kscratch_used_mask; @@ -630,8 +631,14 @@ 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 (cpu_has_rixi) { - UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); + if (cpu_has_rixi && _PAGE_NO_EXEC) { + if (fill_includes_sw_bits) { + UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); + } else { + UASM_i_SRL(p, reg, reg, ilog2(_PAGE_NO_EXEC)); + UASM_i_ROTR(p, reg, reg, + ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC)); + } } else { #ifdef CONFIG_PHYS_ADDR_T_64BIT uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL)); @@ -2338,6 +2345,41 @@ static void config_xpa_params(void) #endif } +static void check_pabits(void) +{ + unsigned long entry; + unsigned pabits, fillbits; + + if (!cpu_has_rixi || !_PAGE_NO_EXEC) { + /* + * We'll only be making use of the fact that we can rotate bits + * into the fill if the CPU supports RIXI, so don't bother + * probing this for CPUs which don't. + */ + return; + } + + write_c0_entrylo0(~0ul); + back_to_back_c0_hazard(); + entry = read_c0_entrylo0(); + + /* clear all non-PFN bits */ + entry &= ~((1 << MIPS_ENTRYLO_PFN_SHIFT) - 1); + entry &= ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); + + /* find a lower bound on PABITS, and upper bound on fill bits */ + pabits = fls_long(entry) + 6; + fillbits = max_t(int, (int)BITS_PER_LONG - pabits, 0); + + /* minus the RI & XI bits */ + fillbits -= min_t(unsigned, fillbits, 2); + + if (fillbits >= ilog2(_PAGE_NO_EXEC)) + fill_includes_sw_bits = true; + + pr_debug("Entry* registers contain %u fill bits\n", fillbits); +} + void build_tlb_refill_handler(void) { /* @@ -2348,6 +2390,7 @@ void build_tlb_refill_handler(void) static int run_once = 0; output_pgtable_bits_defines(); + check_pabits(); #ifdef CONFIG_64BIT check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); From 033549c60969753d9c54053901b2041d91c4fbff Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:42:53 -0700 Subject: [PATCH 041/120] MIPS: Allow RIXI for 32-bit kernels on MIPS64 Commit a68d09a156b2 ("MIPS: Don't use RI/XI with 32-bit kernels on 64-bit CPUs") prevented use of RIXI on MIPS64 systems, stating that the "TLB handlers cannot handle this case". What they actually couldn't handle was cases where there were less fill bits in the Entry{Lo,Hi} registers than bits used by software in PTEs. The handlers can now deal with this case, so enable RIXI for MIPS32 kernels on MIPS64 systems. Note that beyond the obvious benefits provided by having RIXI on such systems, this is required for systems implementing MIPSr6 where RIXI cannot be disabled. This reverts commit a68d09a156b2 ("MIPS: Don't use RI/XI with 32-bit kernels on 64-bit CPUs"). Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11219/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index fe67f12ac239..d1e04c943f5f 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -131,11 +131,7 @@ #endif #ifndef cpu_has_rixi -# ifdef CONFIG_64BIT -# define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) -# else /* CONFIG_32BIT */ -# define cpu_has_rixi ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits) -# endif +#define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) #endif #ifndef cpu_has_mmips From e1137e1d5944c2a23ca100a0b4fe6310f9cc086d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:56:36 -0700 Subject: [PATCH 042/120] MIPS: Malta: Split obj-y entries across lines Split the obj-y entries to their own lines such that it's easier to see what's going on when adding or removing entries. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11220/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index ea35587a5c29..87c85a5b4faf 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -5,9 +5,15 @@ # Copyright (C) 2008 Wind River Systems, Inc. # written by Ralf Baechle # -obj-y := malta-display.o malta-dt.o malta-init.o \ - malta-int.o malta-memory.o malta-platform.o \ - malta-reset.o malta-setup.o malta-time.o +obj-y += malta-display.o +obj-y += malta-dt.o +obj-y += malta-init.o +obj-y += malta-int.o +obj-y += malta-memory.o +obj-y += malta-platform.o +obj-y += malta-reset.o +obj-y += malta-setup.o +obj-y += malta-time.o obj-$(CONFIG_MIPS_CMP) += malta-amon.o obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o From ea050714bc3656a25b4b5fc73f3682532c7180eb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:56:37 -0700 Subject: [PATCH 043/120] MIPS: Malta: Remove fw_memblock_t abstraction The fw_getmdesc function & fw_memblock_t abstraction is only used by Malta, and so far as I can tell serves no purpose beyond making the code less clear than it could be. Remove the useless level of abstraction. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11221/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/fw/fw.h | 16 ----- arch/mips/mti-malta/malta-memory.c | 93 ++++++++++-------------------- 2 files changed, 29 insertions(+), 80 deletions(-) diff --git a/arch/mips/include/asm/fw/fw.h b/arch/mips/include/asm/fw/fw.h index f3e6978aad70..d0ef8b4892bb 100644 --- a/arch/mips/include/asm/fw/fw.h +++ b/arch/mips/include/asm/fw/fw.h @@ -10,21 +10,6 @@ #include /* For cleaner code... */ -enum fw_memtypes { - fw_dontuse, - fw_code, - fw_free, -}; - -typedef struct { - unsigned long base; /* Within KSEG0 */ - unsigned int size; /* bytes */ - enum fw_memtypes type; /* fw_memtypes */ -} fw_memblock_t; - -/* Maximum number of memory block descriptors. */ -#define FW_MAX_MEMBLOCKS 32 - extern int fw_argc; extern int *_fw_argv; extern int *_fw_envp; @@ -38,7 +23,6 @@ extern int *_fw_envp; extern void fw_init_cmdline(void); extern char *fw_getcmdline(void); -extern fw_memblock_t *fw_getmdesc(int); extern void fw_meminit(void); extern char *fw_getenv(char *name); extern unsigned long fw_getenvl(char *name); diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index dadeb8379182..93ace96a1aa8 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -21,19 +21,25 @@ #include #include -static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS]; - /* determined physical memory size, not overridden by command line args */ unsigned long physical_memsize = 0L; -fw_memblock_t * __init fw_getmdesc(int eva) +static void free_init_pages_eva_malta(void *begin, void *end) +{ + free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin), + __pa_symbol((unsigned long *)end)); +} + +void __init fw_meminit(void) { char *memsize_str, *ememsize_str = NULL, *ptr; unsigned long memsize = 0, ememsize = 0; + unsigned long kernel_start_phys, kernel_end_phys; static char cmdline[COMMAND_LINE_SIZE] __initdata; + bool eva = config_enabled(CONFIG_EVA); int tmp; - /* otherwise look in the environment */ + free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL; memsize_str = fw_getenv("memsize"); if (memsize_str) { @@ -92,15 +98,14 @@ fw_memblock_t * __init fw_getmdesc(int eva) if (memsize > 0x7fff0000) memsize = 0x7fff0000; - memset(mdesc, 0, sizeof(mdesc)); + add_memory_region(PHYS_OFFSET, 0x00001000, BOOT_MEM_RESERVED); - mdesc[0].type = fw_dontuse; - mdesc[0].base = PHYS_OFFSET; - mdesc[0].size = 0x00001000; - - mdesc[1].type = fw_code; - mdesc[1].base = mdesc[0].base + 0x00001000UL; - mdesc[1].size = 0x000ef000; + /* + * YAMON may still be using the region of memory from 0x1000 to 0xfffff + * if it has started secondary CPUs. + */ + add_memory_region(PHYS_OFFSET + 0x00001000, 0x000ef000, + BOOT_MEM_ROM_DATA); /* * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the @@ -109,59 +114,19 @@ fw_memblock_t * __init fw_getmdesc(int eva) * This mean that this area can't be used as DMA memory for PCI * devices. */ - mdesc[2].type = fw_dontuse; - mdesc[2].base = mdesc[0].base + 0x000f0000UL; - mdesc[2].size = 0x00010000; + add_memory_region(PHYS_OFFSET + 0x000f0000, 0x00010000, + BOOT_MEM_RESERVED); - mdesc[3].type = fw_dontuse; - mdesc[3].base = mdesc[0].base + 0x00100000UL; - mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - - 0x00100000UL; - - mdesc[4].type = fw_free; - mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end)); - mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base); - - return &mdesc[0]; -} - -static void free_init_pages_eva_malta(void *begin, void *end) -{ - free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin), - __pa_symbol((unsigned long *)end)); -} - -static int __init fw_memtype_classify(unsigned int type) -{ - switch (type) { - case fw_free: - return BOOT_MEM_RAM; - case fw_code: - return BOOT_MEM_ROM_DATA; - default: - return BOOT_MEM_RESERVED; - } -} - -void __init fw_meminit(void) -{ - fw_memblock_t *p; - - p = fw_getmdesc(config_enabled(CONFIG_EVA)); - free_init_pages_eva = (config_enabled(CONFIG_EVA) ? - free_init_pages_eva_malta : NULL); - - while (p->size) { - long type; - unsigned long base, size; - - type = fw_memtype_classify(p->type); - base = p->base; - size = p->size; - - add_memory_region(base, size, type); - p++; - } + /* + * Reserve the memory used by kernel code, and allow the rest of RAM to + * be used. + */ + kernel_start_phys = PHYS_OFFSET + 0x00100000; + kernel_end_phys = PHYS_OFFSET + CPHYSADDR(PFN_ALIGN(&_end)); + add_memory_region(kernel_start_phys, kernel_end_phys, + BOOT_MEM_RESERVED); + add_memory_region(kernel_end_phys, memsize - kernel_end_phys, + BOOT_MEM_RAM); } void __init prom_free_prom_memory(void) From e81a8c7dabac05d444eda315ff1a747b0fe38396 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:56:38 -0700 Subject: [PATCH 044/120] MIPS: Malta: Setup RAM regions via DT Move memory configuration to be performed via device tree for the Malta board. This moves more Malta specific code to malta-dtshim.c, leaving the rest of the mti-malta code a little more board-agnostic. This will be useful to share more code between boards, with the device tree providing the board specifics as intended. Since we can't rely upon Malta boards running a bootloader capable of handling devictrees & filling in the required information, a piece of shim code (malta_dt_shim) is added to consume the (e)memsize variables provided as part of the bootloader environment (or on the kernel command line) then generate the DT memory node using the provided values. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Cc: Kumar Gala Cc: linux-kernel@vger.kernel.org Cc: Ian Campbell Cc: Rob Herring Cc: James Hogan Cc: Pawel Moll Cc: Markos Chandras Cc: Mark Rutland Patchwork: https://patchwork.linux-mips.org/patch/11222/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/boot/dts/mti/malta.dts | 4 + .../include/asm/mach-malta/malta-dtshim.h | 29 ++++ arch/mips/mti-malta/Makefile | 3 + arch/mips/mti-malta/malta-dtshim.c | 162 ++++++++++++++++++ arch/mips/mti-malta/malta-memory.c | 92 ---------- arch/mips/mti-malta/malta-setup.c | 5 +- 7 files changed, 204 insertions(+), 93 deletions(-) create mode 100644 arch/mips/include/asm/mach-malta/malta-dtshim.h create mode 100644 arch/mips/mti-malta/malta-dtshim.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1943377ea491..703438a9698e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -450,6 +450,8 @@ config MIPS_MALTA select SYS_SUPPORTS_ZBOOT select USE_OF select ZONE_DMA32 if 64BIT + select BUILTIN_DTB + select LIBFDT help This enables support for the MIPS Technologies Malta evaluation board. diff --git a/arch/mips/boot/dts/mti/malta.dts b/arch/mips/boot/dts/mti/malta.dts index c678115f5b7f..b18c46637d21 100644 --- a/arch/mips/boot/dts/mti/malta.dts +++ b/arch/mips/boot/dts/mti/malta.dts @@ -1,5 +1,9 @@ /dts-v1/; +/memreserve/ 0x00000000 0x00001000; /* YAMON exception vectors */ +/memreserve/ 0x00001000 0x000ef000; /* YAMON */ +/memreserve/ 0x000f0000 0x00010000; /* PIIX4 ISA memory */ + / { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/mips/include/asm/mach-malta/malta-dtshim.h b/arch/mips/include/asm/mach-malta/malta-dtshim.h new file mode 100644 index 000000000000..cfd777663c64 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/malta-dtshim.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Paul Burton + * + * 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 __MIPS_MALTA_DTSHIM_H__ +#define __MIPS_MALTA_DTSHIM_H__ + +#include + +#ifdef CONFIG_MIPS_MALTA + +extern void __init *malta_dt_shim(void *fdt); + +#else /* !CONFIG_MIPS_MALTA */ + +static inline void *malta_dt_shim(void *fdt) +{ + return fdt; +} + +#endif /* !CONFIG_MIPS_MALTA */ + +#endif /* __MIPS_MALTA_DTSHIM_H__ */ diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 87c85a5b4faf..5827af77c18e 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -7,6 +7,7 @@ # obj-y += malta-display.o obj-y += malta-dt.o +obj-y += malta-dtshim.o obj-y += malta-init.o obj-y += malta-int.o obj-y += malta-memory.o @@ -17,3 +18,5 @@ obj-y += malta-time.o obj-$(CONFIG_MIPS_CMP) += malta-amon.o obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o + +CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c new file mode 100644 index 000000000000..f7133efc5843 --- /dev/null +++ b/arch/mips/mti-malta/malta-dtshim.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Paul Burton + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned char fdt_buf[16 << 10] __initdata; + +/* determined physical memory size, not overridden by command line args */ +extern unsigned long physical_memsize; + +#define MAX_MEM_ARRAY_ENTRIES 1 + +static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size) +{ + unsigned long size_preio; + unsigned entries; + + entries = 1; + mem_array[0] = cpu_to_be32(PHYS_OFFSET); + if (config_enabled(CONFIG_EVA)) { + /* + * The current Malta EVA configuration is "special" in that it + * always makes use of addresses in the upper half of the 32 bit + * physical address map, which gives it a contiguous region of + * DDR but limits it to 2GB. + */ + mem_array[1] = cpu_to_be32(size); + } else { + size_preio = min_t(unsigned long, size, SZ_256M); + mem_array[1] = cpu_to_be32(size_preio); + } + + BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES); + return entries; +} + +static void __init append_memory(void *fdt, int root_off) +{ + __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES]; + unsigned long memsize; + unsigned mem_entries; + int i, err, mem_off; + char *var, param_name[10], *var_names[] = { + "ememsize", "memsize", + }; + + /* if a memory node already exists, leave it alone */ + mem_off = fdt_path_offset(fdt, "/memory"); + if (mem_off >= 0) + return; + + /* find memory size from the bootloader environment */ + for (i = 0; i < ARRAY_SIZE(var_names); i++) { + var = fw_getenv(var_names[i]); + if (!var) + continue; + + err = kstrtoul(var, 0, &physical_memsize); + if (!err) + break; + + pr_warn("Failed to read the '%s' env variable '%s'\n", + var_names[i], var); + } + + if (!physical_memsize) { + pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n"); + physical_memsize = 32 << 20; + } + + if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) { + /* + * SOC-it swaps, or perhaps doesn't swap, when DMA'ing + * the last word of physical memory. + */ + physical_memsize -= PAGE_SIZE; + } + + /* default to using all available RAM */ + memsize = physical_memsize; + + /* allow the user to override the usable memory */ + for (i = 0; i < ARRAY_SIZE(var_names); i++) { + snprintf(param_name, sizeof(param_name), "%s=", var_names[i]); + var = strstr(arcs_cmdline, param_name); + if (!var) + continue; + + memsize = memparse(var + strlen(param_name), NULL); + } + + /* if the user says there's more RAM than we thought, believe them */ + physical_memsize = max_t(unsigned long, physical_memsize, memsize); + + /* append memory to the DT */ + mem_off = fdt_add_subnode(fdt, root_off, "memory"); + if (mem_off < 0) + panic("Unable to add memory node to DT: %d", mem_off); + + err = fdt_setprop_string(fdt, mem_off, "device_type", "memory"); + if (err) + panic("Unable to set memory node device_type: %d", err); + + mem_entries = gen_fdt_mem_array(mem_array, physical_memsize); + err = fdt_setprop(fdt, mem_off, "reg", mem_array, + mem_entries * 2 * sizeof(mem_array[0])); + if (err) + panic("Unable to set memory regs property: %d", err); + + mem_entries = gen_fdt_mem_array(mem_array, memsize); + err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array, + mem_entries * 2 * sizeof(mem_array[0])); + if (err) + panic("Unable to set linux,usable-memory property: %d", err); +} + +void __init *malta_dt_shim(void *fdt) +{ + int root_off, len, err; + const char *compat; + + if (fdt_check_header(fdt)) + panic("Corrupt DT"); + + err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf)); + if (err) + panic("Unable to open FDT: %d", err); + + root_off = fdt_path_offset(fdt_buf, "/"); + if (root_off < 0) + panic("No / node in DT"); + + compat = fdt_getprop(fdt_buf, root_off, "compatible", &len); + if (!compat) + panic("No root compatible property in DT: %d", len); + + /* if this isn't Malta, leave the DT alone */ + if (strncmp(compat, "mti,malta", len)) + return fdt; + + append_memory(fdt_buf, root_off); + + err = fdt_pack(fdt_buf); + if (err) + panic("Unable to pack FDT: %d\n", err); + + return fdt_buf; +} diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index 93ace96a1aa8..d5f8dae6a797 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -32,101 +32,9 @@ static void free_init_pages_eva_malta(void *begin, void *end) void __init fw_meminit(void) { - char *memsize_str, *ememsize_str = NULL, *ptr; - unsigned long memsize = 0, ememsize = 0; - unsigned long kernel_start_phys, kernel_end_phys; - static char cmdline[COMMAND_LINE_SIZE] __initdata; bool eva = config_enabled(CONFIG_EVA); - int tmp; free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL; - - memsize_str = fw_getenv("memsize"); - if (memsize_str) { - tmp = kstrtoul(memsize_str, 0, &memsize); - if (tmp) - pr_warn("Failed to read the 'memsize' env variable.\n"); - } - if (eva) { - /* Look for ememsize for EVA */ - ememsize_str = fw_getenv("ememsize"); - if (ememsize_str) { - tmp = kstrtoul(ememsize_str, 0, &ememsize); - if (tmp) - pr_warn("Failed to read the 'ememsize' env variable.\n"); - } - } - if (!memsize && !ememsize) { - pr_warn("memsize not set in YAMON, set to default (32Mb)\n"); - physical_memsize = 0x02000000; - } else { - if (memsize > (256 << 20)) { /* memsize should be capped to 256M */ - pr_warn("Unsupported memsize value (0x%lx) detected! " - "Using 0x10000000 (256M) instead\n", - memsize); - memsize = 256 << 20; - } - /* If ememsize is set, then set physical_memsize to that */ - physical_memsize = ememsize ? : memsize; - } - -#ifdef CONFIG_CPU_BIG_ENDIAN - /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last - word of physical memory */ - physical_memsize -= PAGE_SIZE; -#endif - - /* Check the command line for a memsize directive that overrides - the physical/default amount */ - strcpy(cmdline, arcs_cmdline); - ptr = strstr(cmdline, "memsize="); - if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) - ptr = strstr(ptr, " memsize="); - /* And now look for ememsize */ - if (eva) { - ptr = strstr(cmdline, "ememsize="); - if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) - ptr = strstr(ptr, " ememsize="); - } - - if (ptr) - memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr); - else - memsize = physical_memsize; - - /* Last 64K for HIGHMEM arithmetics */ - if (memsize > 0x7fff0000) - memsize = 0x7fff0000; - - add_memory_region(PHYS_OFFSET, 0x00001000, BOOT_MEM_RESERVED); - - /* - * YAMON may still be using the region of memory from 0x1000 to 0xfffff - * if it has started secondary CPUs. - */ - add_memory_region(PHYS_OFFSET + 0x00001000, 0x000ef000, - BOOT_MEM_ROM_DATA); - - /* - * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the - * south bridge and PCI access always forwarded to the ISA Bus and - * BIOSCS# is always generated. - * This mean that this area can't be used as DMA memory for PCI - * devices. - */ - add_memory_region(PHYS_OFFSET + 0x000f0000, 0x00010000, - BOOT_MEM_RESERVED); - - /* - * Reserve the memory used by kernel code, and allow the rest of RAM to - * be used. - */ - kernel_start_phys = PHYS_OFFSET + 0x00100000; - kernel_end_phys = PHYS_OFFSET + CPHYSADDR(PFN_ALIGN(&_end)); - add_memory_region(kernel_start_phys, kernel_end_phys, - BOOT_MEM_RESERVED); - add_memory_region(kernel_end_phys, memsize - kernel_end_phys, - BOOT_MEM_RAM); } void __init prom_free_prom_memory(void) diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index 9d1e7f5ec36c..4740c82fb97a 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -250,8 +251,10 @@ static void __init bonito_quirks_setup(void) void __init plat_mem_setup(void) { unsigned int i; + void *fdt = __dtb_start; - __dt_setup_arch(__dtb_start); + fdt = malta_dt_shim(fdt); + __dt_setup_arch(fdt); if (config_enabled(CONFIG_EVA)) /* EVA has already been configured in mach-malta/kernel-init.h */ From ecafe3e9b27644b51282b539878b7671ea28ac34 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:58:43 -0700 Subject: [PATCH 045/120] MIPS: Malta: Register UP SMP ops if all else fails If we fail to register any real SMP implementations, fall back to registering the dummy UP implementation. Otherwise when we build an SMP kernel & run it on a system where the SMP implementations fail to probe (eg. QEMU) the kernel will perform a NULL dereference attempting to call mp_ops->smp_setup() from plat_smp_setup(). Notably this fixes booting kernels with CPS SMP enabled on QEMU, which doesn't currently implement the CM, CPC or GIC. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Peter Hurley Cc: Rob Herring Cc: linux-kernel@vger.kernel.org Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11223/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/mti-malta/malta-init.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 703438a9698e..9322d267e774 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -425,6 +425,7 @@ config MIPS_MALTA select MIPS_L1_CACHE_SHIFT_6 select PCI_GT64XXX_PCI0 select MIPS_MSC + select SMP_UP if SMP select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 53c24784a2f7..571148c5fd0b 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -302,6 +302,7 @@ mips_pci_controller: return; if (!register_vsmp_smp_ops()) return; + register_up_smp_ops(); } void platform_early_l2_init(void) From cab25bc7537badea41f635a049f45408c24dff26 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 12:03:37 -0700 Subject: [PATCH 046/120] MIPS: Extend hardware table walking support to MIPS64 Extend the existing support for Hardware Table Walking (HTW) to MIPS64 systems by supporting PMDs & setting the pointer size bit in PWSize, then ceasing to blacklist HTW on MIPS64 systems. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: Maciej W. Rozycki Cc: Paul Gortmaker Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11224/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 3 +-- arch/mips/mm/tlbex.c | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 09a51d091941..6b9064499bd3 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -536,8 +536,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_SEGMENTS; if (config3 & MIPS_CONF3_MSA) c->ases |= MIPS_ASE_MSA; - /* Only tested on 32-bit cores */ - if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) { + if (config3 & MIPS_CONF3_PW) { c->htw_seq = 0; c->options |= MIPS_CPU_HTW; } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 6b7cc20efd92..32e0be27673f 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2284,6 +2284,10 @@ static void config_htw_params(void) /* re-initialize the PTI field including the even/odd bit */ pwfield &= ~MIPS_PWFIELD_PTI_MASK; pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT; + if (CONFIG_PGTABLE_LEVELS >= 3) { + pwfield &= ~MIPS_PWFIELD_MDI_MASK; + pwfield |= PMD_SHIFT << MIPS_PWFIELD_MDI_SHIFT; + } /* Set the PTEI right shift */ ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT; pwfield |= ptei; @@ -2305,9 +2309,11 @@ static void config_htw_params(void) pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT; pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT; + 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 (read_c0_pagegrain() & PG_ELPA) + if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA)) pwsize |= 1; write_c0_pwsize(pwsize); From adcdd4287da33132d4a72a9bcf60183c1cab5563 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:42 +0200 Subject: [PATCH 047/120] MIPS: bigsur_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts bigsur_defconfig to use libata PATA drivers (tc86c001 IDE host driver has no corresponding libata driver yet so it is not converted). Signed-off-by: Bartlomiej Zolnierkiewicz Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11128/ Signed-off-by: Ralf Baechle --- arch/mips/configs/bigsur_defconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index 1cdff6b6327d..b3e7a1b61220 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -122,20 +122,20 @@ CONFIG_EEPROM_MAX6875=y CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=m -CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_CHR_DEV_SCH=m CONFIG_ATA=y CONFIG_SATA_SIL24=y +CONFIG_PATA_CMD64X=y +CONFIG_PATA_IT8213=m CONFIG_PATA_SIL680=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_MII=y From 5081f4fc32243c3ebbd95638abd3ef1a2ae1247f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:43 +0200 Subject: [PATCH 048/120] MIPS: capcella_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts capcella_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11129/ Signed-off-by: Ralf Baechle --- arch/mips/configs/capcella_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig index 5135dc0b950a..2924ba34a01b 100644 --- a/arch/mips/configs/capcella_defconfig +++ b/arch/mips/configs/capcella_defconfig @@ -31,9 +31,9 @@ CONFIG_NETWORK_SECMARK=y CONFIG_IP_SCTP=m CONFIG_FW_LOADER=m CONFIG_BLK_DEV_RAM=y -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_PATA_LEGACY=y CONFIG_NETDEVICES=y CONFIG_PHYLIB=m CONFIG_MARVELL_PHY=m From 5c2a53a1e0ee8713b9160a52ed374cc8d8cd0c82 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:44 +0200 Subject: [PATCH 049/120] MIPS: e55_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts e55_defconfig to use libata PATA drivers. PS This platform still uses "ide0=base[,ctl[,irq]]" hack in its defconfig. The hack itself has been removed in 2008 and this platform should be converted to using PATA platform host driver (pata_platform) instead. Cc: Yoichi Yuasa Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Ralf Baechle --- arch/mips/configs/e55_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig index 0126e66d60cb..e94d266c4b97 100644 --- a/arch/mips/configs/e55_defconfig +++ b/arch/mips/configs/e55_defconfig @@ -14,9 +14,9 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_BLK_DEV_RAM=y -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_PATA_LEGACY=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set From 1485ddcc2ffaaa801c4104b85eac95c2f32c4220 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:45 +0200 Subject: [PATCH 050/120] MIPS: fuloong2e_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts fuloong2e_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11131/ Signed-off-by: Ralf Baechle --- arch/mips/configs/fuloong2e_defconfig | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index a75c65da08b4..87435897fd50 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig @@ -34,7 +34,7 @@ CONFIG_MIPS32_N32=y CONFIG_PM=y # CONFIG_SUSPEND is not set CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="/dev/hda3" +CONFIG_PM_STD_PARTITION="/dev/sda3" CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -114,20 +114,16 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_RAM=m CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_BLK_DEV_IDECD=y -CONFIG_IDE_TASK_IOCTL=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_VIA82CXXX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_PATA_VIA=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_NETDEVICES=y CONFIG_MACVLAN=m CONFIG_VETH=m From 973852fc0d1be1fa47a03c7c0a106a0667714edd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:46 +0200 Subject: [PATCH 051/120] MIPS: lasat_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts lasat_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Brian Murphy Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11132/ Signed-off-by: Ralf Baechle --- arch/mips/configs/lasat_defconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig index 0179c7fa014f..e620a2c3eba4 100644 --- a/arch/mips/configs/lasat_defconfig +++ b/arch/mips/configs/lasat_defconfig @@ -35,11 +35,11 @@ CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_PATA_CMD64X=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_NET_PCI=y From 7ff7a5b1bfff71a1814f3542c1bd3c8f3e08bbbe Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:47 +0200 Subject: [PATCH 052/120] MIPS: lemote2f_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts lemote2f_defconfig to use libata PATA drivers. PS This platform uses CS5536 chipset which (due to historical reasons) has basic support in AMD/nVidia PATA host driver and full support in a newer CS5536 PATA one (pata_cs5536). Thus most likely this platform should switch to using the latter host driver. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Huacai Chen Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11133/ Signed-off-by: Ralf Baechle --- arch/mips/configs/lemote2f_defconfig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig index 54cc3853d259..004cf52d1b7d 100644 --- a/arch/mips/configs/lemote2f_defconfig +++ b/arch/mips/configs/lemote2f_defconfig @@ -108,16 +108,11 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_IDE_TASK_IOCTL=y -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_AMD74XX=y -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=m -CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_PATA_AMD=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m From d17e465543e7689168ea2a913e67231876a668d5 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:48 +0200 Subject: [PATCH 053/120] MIPS: malta_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts malta_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11134/ Signed-off-by: Ralf Baechle --- arch/mips/configs/malta_defconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 61a4460d67d3..5afb4840aec7 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -241,14 +241,11 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m -CONFIG_IDE=y -CONFIG_BLK_DEV_IDECD=y -CONFIG_IDE_GENERIC=y CONFIG_RAID_ATTRS=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y @@ -265,6 +262,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set CONFIG_ATA=y CONFIG_ATA_PIIX=y +CONFIG_PATA_LEGACY=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m From 91c6fbabaed76ce0d85c357fe2f9e9dfc74d0640 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:49 +0200 Subject: [PATCH 054/120] MIPS: malta_kvm_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts malta_kvm_defconfig to use libata PATA drivers (tc86c001 IDE host driver has no corresponding libata driver yet so it is not converted). Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Sanjay Lal Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11135/ Signed-off-by: Ralf Baechle --- arch/mips/configs/malta_kvm_defconfig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig index d41742dd26c8..98f13879bb8f 100644 --- a/arch/mips/configs/malta_kvm_defconfig +++ b/arch/mips/configs/malta_kvm_defconfig @@ -248,17 +248,12 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_MULTI_LUN=y @@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_IT8213=m +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m From 5f6df05b2faf893bc119d4bf1ef2decefedd0440 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:50 +0200 Subject: [PATCH 055/120] MIPS: malta_kvm_guest_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts malta_kvm_guest_defconfig to use libata PATA drivers (tc86c001 IDE host driver has no corresponding libata driver yet so it is not converted). Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Sanjay Lal Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11136/ Signed-off-by: Ralf Baechle --- arch/mips/configs/malta_kvm_guest_defconfig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig index a7806e83ea0f..3b5d5913f548 100644 --- a/arch/mips/configs/malta_kvm_guest_defconfig +++ b/arch/mips/configs/malta_kvm_guest_defconfig @@ -248,17 +248,12 @@ CONFIG_ATA_OVER_ETH=m CONFIG_VIRTIO_BLK=y CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_MULTI_LUN=y @@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_IT8213=m +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m From 077b649a2ffe53109c98379fe7ba2fa4fdc9a34a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:51 +0200 Subject: [PATCH 056/120] MIPS: malta_qemu_32r6_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts malta_qemu_32r6_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Markos Chandras Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: b.zolnierkie@samsung.com Patchwork: https://patchwork.linux-mips.org/patch/11138/ Signed-off-by: Ralf Baechle --- arch/mips/configs/malta_qemu_32r6_defconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig index 4bce1f8ebe98..7f50dd67aa8d 100644 --- a/arch/mips/configs/malta_qemu_32r6_defconfig +++ b/arch/mips/configs/malta_qemu_32r6_defconfig @@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set From 255faa84276ae8c42a660af3ad6e089ac89d22b4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:52 +0200 Subject: [PATCH 057/120] MIPS: maltaaprp_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts maltaaprp_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: b.zolnierkie@samsung.com Patchwork: https://patchwork.linux-mips.org/patch/11137/ Signed-off-by: Ralf Baechle --- arch/mips/configs/maltaaprp_defconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig index fb042ce86b4b..a9d433a17fcf 100644 --- a/arch/mips/configs/maltaaprp_defconfig +++ b/arch/mips/configs/maltaaprp_defconfig @@ -81,15 +81,14 @@ CONFIG_NET_CLS_IND=y CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set From b0b98ad9b59f2a4c011d4b1ff40efa663b2b4e43 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:53 +0200 Subject: [PATCH 058/120] MIPS: maltasmvp_eva_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts maltasmvp_eva_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11139/ Signed-off-by: Ralf Baechle --- arch/mips/configs/maltasmvp_eva_defconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig index c83338a39917..2774ef064505 100644 --- a/arch/mips/configs/maltasmvp_eva_defconfig +++ b/arch/mips/configs/maltasmvp_eva_defconfig @@ -85,15 +85,14 @@ CONFIG_NET_CLS_IND=y CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set From 93c7e664ff6af49c05d1b78b54aa6f02e1ba88f6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:54 +0200 Subject: [PATCH 059/120] MIPS: maltaup_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts maltaup_defconfig to use libata PATA drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11142/ Signed-off-by: Ralf Baechle --- arch/mips/configs/maltaup_defconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig index 62344648eb7a..9bbd2218f0bf 100644 --- a/arch/mips/configs/maltaup_defconfig +++ b/arch/mips/configs/maltaup_defconfig @@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set From 1b7d801263522d9e1a122a6913c42acb5bf6c2c0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:55 +0200 Subject: [PATCH 060/120] MIPS: maltaup_xpa_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts maltaup_xpa_defconfig to use libata PATA drivers (tc86c001 IDE host driver has no corresponding libata driver yet so it is not converted). Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Paul Burton Cc: Markos Chandras Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11140/ Signed-off-by: Ralf Baechle --- arch/mips/configs/maltaup_xpa_defconfig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig index c388bff09148..732215732751 100644 --- a/arch/mips/configs/maltaup_xpa_defconfig +++ b/arch/mips/configs/maltaup_xpa_defconfig @@ -244,17 +244,12 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y @@ -269,6 +264,13 @@ CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_ATA=y +CONFIG_ATA_PIIX=y +CONFIG_PATA_IT8213=m +CONFIG_PATA_OLDPIIX=y +CONFIG_PATA_MPIIX=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_LEGACY=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m From 22773aa9b95657f0adc2b5342428d9da7a6d5d02 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 14 Sep 2015 17:51:56 +0200 Subject: [PATCH 061/120] MIPS: mpc30x_defconfig: Convert to use libata PATA drivers IDE subsystem has been deprecated since 2009 and the majority (if not all) of Linux distributions have switched to use libata for ATA support exclusively. However there are still some users (mostly old or/and embedded non-x86 systems) that have not converted from using IDE subsystem to libata PATA drivers. This doesn't seem to be good thing in the long-term for Linux as while there is less and less PATA systems left in use: * testing efforts are divided between two subsystems * having duplicate drivers for same hardware confuses users This patch converts mpc30x_defconfig to use libata PATA drivers. PS This platform still uses "ide0=base[,ctl[,irq]]" hack in its defconfig. The hack itself has been removed in 2008 and this platform should be converted to using PATA platform host driver (pata_platform) instead. Signed-off-by: Bartlomiej Zolnierkiewicz Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11141/ Signed-off-by: Ralf Baechle --- arch/mips/configs/mpc30x_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig index 7a346605c498..a2c045fab6c5 100644 --- a/arch/mips/configs/mpc30x_defconfig +++ b/arch/mips/configs/mpc30x_defconfig @@ -27,9 +27,9 @@ CONFIG_INET_XFRM_MODE_BEET=m CONFIG_NETWORK_SECMARK=y CONFIG_CONNECTOR=m CONFIG_ATA_OVER_ETH=m -# CONFIG_MISC_DEVICES is not set -CONFIG_IDE=y -CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_PATA_LEGACY=y CONFIG_NETDEVICES=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set From ebb5e78cc63417a35254a791de66e1cc84f963cc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 21 Oct 2015 09:54:38 +0100 Subject: [PATCH 062/120] MIPS: Initial implementation of a VDSO Add an initial implementation of a proper (i.e. an ELF shared library) VDSO. With this commit it does not export any symbols, it only replaces the current signal return trampoline page. A later commit will add user implementations of gettimeofday()/clock_gettime(). To support both new toolchains and old ones which don't generate ABI flags section, we define its content manually and then use a tool (genvdso) to patch up the section to have the correct name and type. genvdso also extracts symbol offsets ({,rt_}sigreturn) needed by the kernel, and generates a C file containing a "struct mips_vdso_image" containing both the VDSO data and these offsets. This C file is compiled into the kernel. On 64-bit kernels we require a different VDSO for each supported ABI, so we may build up to 3 different VDSOs. The VDSO to use is selected by the mips_abi structure. A kernel/user shared data page is created and mapped below the VDSO image. This is currently empty, but will be used by the user time function implementations which are added later. [markos.chandras@imgtec.com: - Add more comments - Move abi detection in genvdso.h since it's the get_symbol function that needs it. - Add an R6 specific way to calculate the base address of VDSO in order to avoid the branch instruction which affects performance. - Do not patch .gnu.attributes since it's not needed for dynamic linking. - Simplify Makefile a little bit. - checkpatch fixes - Restrict VDSO support for binutils < 2.25 for pre-R6 - Include atomic64.h for O32 variant on MIPS64] Signed-off-by: Alex Smith Signed-off-by: Markos Chandras Cc: Matthew Fortune Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11337/ Signed-off-by: Ralf Baechle --- arch/mips/Kbuild | 1 + arch/mips/include/asm/abi.h | 5 +- arch/mips/include/asm/elf.h | 7 + arch/mips/include/asm/processor.h | 8 +- arch/mips/include/asm/vdso.h | 73 +++++-- arch/mips/include/uapi/asm/Kbuild | 2 +- arch/mips/include/uapi/asm/auxvec.h | 17 ++ arch/mips/kernel/signal.c | 12 +- arch/mips/kernel/signal32.c | 7 +- arch/mips/kernel/signal_n32.c | 5 +- arch/mips/kernel/vdso.c | 158 ++++++++------- arch/mips/vdso/.gitignore | 4 + arch/mips/vdso/Makefile | 160 +++++++++++++++ arch/mips/vdso/elf.S | 68 +++++++ arch/mips/vdso/genvdso.c | 293 ++++++++++++++++++++++++++++ arch/mips/vdso/genvdso.h | 187 ++++++++++++++++++ arch/mips/vdso/sigreturn.S | 49 +++++ arch/mips/vdso/vdso.h | 80 ++++++++ arch/mips/vdso/vdso.lds.S | 100 ++++++++++ 19 files changed, 1113 insertions(+), 123 deletions(-) create mode 100644 arch/mips/include/uapi/asm/auxvec.h create mode 100644 arch/mips/vdso/.gitignore create mode 100644 arch/mips/vdso/Makefile create mode 100644 arch/mips/vdso/elf.S create mode 100644 arch/mips/vdso/genvdso.c create mode 100644 arch/mips/vdso/genvdso.h create mode 100644 arch/mips/vdso/sigreturn.S create mode 100644 arch/mips/vdso/vdso.h create mode 100644 arch/mips/vdso/vdso.lds.S diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index dd295335891a..5c3f688a5232 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -17,6 +17,7 @@ obj- := $(platform-) obj-y += kernel/ obj-y += mm/ obj-y += net/ +obj-y += vdso/ ifdef CONFIG_KVM obj-y += kvm/ diff --git a/arch/mips/include/asm/abi.h b/arch/mips/include/asm/abi.h index 37f84078e78a..940760844e2f 100644 --- a/arch/mips/include/asm/abi.h +++ b/arch/mips/include/asm/abi.h @@ -11,19 +11,20 @@ #include #include +#include struct mips_abi { int (* const setup_frame)(void *sig_return, struct ksignal *ksig, struct pt_regs *regs, sigset_t *set); - const unsigned long signal_return_offset; int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig, struct pt_regs *regs, sigset_t *set); - const unsigned long rt_signal_return_offset; const unsigned long restart; unsigned off_sc_fpregs; unsigned off_sc_fpc_csr; unsigned off_sc_used_math; + + struct mips_vdso_image *vdso; }; #endif /* _ASM_ABI_H */ diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 53b26933b12c..b01a6ff468e0 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -8,6 +8,7 @@ #ifndef _ASM_ELF_H #define _ASM_ELF_H +#include #include #include @@ -419,6 +420,12 @@ extern const char *__elf_platform; #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) #endif +#define ARCH_DLINFO \ +do { \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, \ + (unsigned long)current->mm->context.vdso); \ +} while (0) + #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 struct linux_binprm; extern int arch_setup_additional_pages(struct linux_binprm *bprm, diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 59ee6dcf6eed..3f832c3dd8f5 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count; */ #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 -/* - * A special page (the vdso) is mapped into all processes at the very - * top of the virtual memory space. - */ -#define SPECIAL_PAGES_SIZE PAGE_SIZE - #ifdef CONFIG_32BIT #ifdef CONFIG_KVM_GUEST /* User space process size is limited to 1GB in KVM Guest Mode */ @@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count; #endif -#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE) +#define STACK_TOP (TASK_SIZE & PAGE_MASK) /* * This decides where the kernel will search for a free chunk of vm diff --git a/arch/mips/include/asm/vdso.h b/arch/mips/include/asm/vdso.h index cca56aa40ff4..db2d45be8f2e 100644 --- a/arch/mips/include/asm/vdso.h +++ b/arch/mips/include/asm/vdso.h @@ -1,29 +1,70 @@ /* - * 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) 2015 Imagination Technologies + * Author: Alex Smith * - * Copyright (C) 2009 Cavium Networks + * 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_VDSO_H #define __ASM_VDSO_H -#include +#include +/** + * struct mips_vdso_image - Details of a VDSO image. + * @data: Pointer to VDSO image data (page-aligned). + * @size: Size of the VDSO image data (page-aligned). + * @off_sigreturn: Offset of the sigreturn() trampoline. + * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline. + * @mapping: Special mapping structure. + * + * This structure contains details of a VDSO image, including the image data + * and offsets of certain symbols required by the kernel. It is generated as + * part of the VDSO build process, aside from the mapping page array, which is + * populated at runtime. + */ +struct mips_vdso_image { + void *data; + unsigned long size; -#ifdef CONFIG_32BIT -struct mips_vdso { - u32 signal_trampoline[2]; - u32 rt_signal_trampoline[2]; + unsigned long off_sigreturn; + unsigned long off_rt_sigreturn; + + struct vm_special_mapping mapping; }; -#else /* !CONFIG_32BIT */ -struct mips_vdso { - u32 o32_signal_trampoline[2]; - u32 o32_rt_signal_trampoline[2]; - u32 rt_signal_trampoline[2]; - u32 n32_rt_signal_trampoline[2]; + +/* + * The following structures are auto-generated as part of the build for each + * ABI by genvdso, see arch/mips/vdso/Makefile. + */ + +extern struct mips_vdso_image vdso_image; + +#ifdef CONFIG_MIPS32_O32 +extern struct mips_vdso_image vdso_image_o32; +#endif + +#ifdef CONFIG_MIPS32_N32 +extern struct mips_vdso_image vdso_image_n32; +#endif + +/** + * union mips_vdso_data - Data provided by the kernel for the VDSO. + * + * This structure contains data needed by functions within the VDSO. It is + * populated by the kernel and mapped read-only into user memory. + * + * Note: Care should be taken when modifying as the layout must remain the same + * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel). + */ +union mips_vdso_data { + struct { + }; + + u8 page[PAGE_SIZE]; }; -#endif /* CONFIG_32BIT */ #endif /* __ASM_VDSO_H */ diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index 96fe7395ed8d..f2cf41461146 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -1,9 +1,9 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -generic-y += auxvec.h generic-y += ipcbuf.h +header-y += auxvec.h header-y += bitfield.h header-y += bitsperlong.h header-y += break.h diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h new file mode 100644 index 000000000000..c9c7195272c4 --- /dev/null +++ b/arch/mips/include/uapi/asm/auxvec.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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_AUXVEC_H +#define __ASM_AUXVEC_H + +/* Location of VDSO image. */ +#define AT_SYSINFO_EHDR 33 + +#endif /* __ASM_AUXVEC_H */ diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 2fec67bfc457..bf792e2839a6 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -752,16 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig, struct mips_abi mips_abi = { #ifdef CONFIG_TRAD_SIGNALS .setup_frame = setup_frame, - .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline), #endif .setup_rt_frame = setup_rt_frame, - .rt_signal_return_offset = - offsetof(struct mips_vdso, rt_signal_trampoline), .restart = __NR_restart_syscall, .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs), .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr), .off_sc_used_math = offsetof(struct sigcontext, sc_used_math), + + .vdso = &vdso_image, }; static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) @@ -801,11 +799,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) } if (sig_uses_siginfo(&ksig->ka)) - ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, + ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn, ksig, regs, oldset); else - ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig, - regs, oldset); + ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn, + ksig, regs, oldset); signal_setup_done(ret, ksig, 0); } diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index f7e89524e316..4909639aa35b 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "signal-common.h" @@ -406,14 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig, */ struct mips_abi mips_abi_32 = { .setup_frame = setup_frame_32, - .signal_return_offset = - offsetof(struct mips_vdso, o32_signal_trampoline), .setup_rt_frame = setup_rt_frame_32, - .rt_signal_return_offset = - offsetof(struct mips_vdso, o32_rt_signal_trampoline), .restart = __NR_O32_restart_syscall, .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs), .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr), .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math), + + .vdso = &vdso_image_o32, }; diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 0d017fdcaf07..a7bc38430500 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "signal-common.h" @@ -151,11 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig, struct mips_abi mips_abi_n32 = { .setup_rt_frame = setup_rt_frame_n32, - .rt_signal_return_offset = - offsetof(struct mips_vdso, n32_rt_signal_trampoline), .restart = __NR_N32_restart_syscall, .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs), .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr), .off_sc_used_math = offsetof(struct sigcontext, sc_used_math), + + .vdso = &vdso_image_n32, }; diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index ed2a278722a9..56cc3c4377fb 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -1,122 +1,116 @@ /* - * 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) 2015 Imagination Technologies + * Author: Alex Smith * - * Copyright (C) 2009, 2010 Cavium Networks, Inc. + * 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. */ - -#include -#include -#include -#include -#include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include + +/* Kernel-provided data used by the VDSO. */ +static union mips_vdso_data vdso_data __page_aligned_data; /* - * Including would give use the 64-bit syscall numbers ... + * Mapping for the VDSO data pages. The real pages are mapped manually, as + * what we map and where within the area they are mapped is determined at + * runtime. */ -#define __NR_O32_sigreturn 4119 -#define __NR_O32_rt_sigreturn 4193 -#define __NR_N32_rt_sigreturn 6211 +static struct page *no_pages[] = { NULL }; +static struct vm_special_mapping vdso_vvar_mapping = { + .name = "[vvar]", + .pages = no_pages, +}; -static struct page *vdso_page; - -static void __init install_trampoline(u32 *tramp, unsigned int sigreturn) +static void __init init_vdso_image(struct mips_vdso_image *image) { - uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */ - uasm_i_syscall(&tramp, 0); + unsigned long num_pages, i; + + BUG_ON(!PAGE_ALIGNED(image->data)); + BUG_ON(!PAGE_ALIGNED(image->size)); + + num_pages = image->size / PAGE_SIZE; + + for (i = 0; i < num_pages; i++) { + image->mapping.pages[i] = + virt_to_page(image->data + (i * PAGE_SIZE)); + } } static int __init init_vdso(void) { - struct mips_vdso *vdso; + init_vdso_image(&vdso_image); - vdso_page = alloc_page(GFP_KERNEL); - if (!vdso_page) - panic("Cannot allocate vdso"); - - vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL); - if (!vdso) - panic("Cannot map vdso"); - clear_page(vdso); - - install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn); -#ifdef CONFIG_32BIT - install_trampoline(vdso->signal_trampoline, __NR_sigreturn); -#else - install_trampoline(vdso->n32_rt_signal_trampoline, - __NR_N32_rt_sigreturn); - install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn); - install_trampoline(vdso->o32_rt_signal_trampoline, - __NR_O32_rt_sigreturn); +#ifdef CONFIG_MIPS32_O32 + init_vdso_image(&vdso_image_o32); #endif - vunmap(vdso); +#ifdef CONFIG_MIPS32_N32 + init_vdso_image(&vdso_image_n32); +#endif return 0; } subsys_initcall(init_vdso); -static unsigned long vdso_addr(unsigned long start) -{ - unsigned long offset = 0UL; - - if (current->flags & PF_RANDOMIZE) { - offset = get_random_int(); - offset <<= PAGE_SHIFT; - if (TASK_IS_32BIT_ADDR) - offset &= 0xfffffful; - else - offset &= 0xffffffful; - } - - return STACK_TOP + offset; -} - int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { - int ret; - unsigned long addr; + struct mips_vdso_image *image = current->thread.abi->vdso; struct mm_struct *mm = current->mm; + unsigned long base, vdso_addr; + struct vm_area_struct *vma; + int ret; down_write(&mm->mmap_sem); - addr = vdso_addr(mm->start_stack); - - addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0); - if (IS_ERR_VALUE(addr)) { - ret = addr; - goto up_fail; + base = get_unmapped_area(NULL, 0, PAGE_SIZE + image->size, 0, 0); + if (IS_ERR_VALUE(base)) { + ret = base; + goto out; } - ret = install_special_mapping(mm, addr, PAGE_SIZE, - VM_READ|VM_EXEC| - VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - &vdso_page); + vdso_addr = base + PAGE_SIZE; + vma = _install_special_mapping(mm, base, PAGE_SIZE, + VM_READ | VM_MAYREAD, + &vdso_vvar_mapping); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto out; + } + + /* Map data page. */ + ret = remap_pfn_range(vma, base, + virt_to_phys(&vdso_data) >> PAGE_SHIFT, + PAGE_SIZE, PAGE_READONLY); if (ret) - goto up_fail; + goto out; - mm->context.vdso = (void *)addr; + /* Map VDSO image. */ + vma = _install_special_mapping(mm, vdso_addr, image->size, + VM_READ | VM_EXEC | + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, + &image->mapping); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto out; + } -up_fail: + mm->context.vdso = (void *)vdso_addr; + ret = 0; + +out: up_write(&mm->mmap_sem); return ret; } - -const char *arch_vma_name(struct vm_area_struct *vma) -{ - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) - return "[vdso]"; - return NULL; -} diff --git a/arch/mips/vdso/.gitignore b/arch/mips/vdso/.gitignore new file mode 100644 index 000000000000..5286a7d73d79 --- /dev/null +++ b/arch/mips/vdso/.gitignore @@ -0,0 +1,4 @@ +*.so* +vdso-*image.c +genvdso +vdso*.lds diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile new file mode 100644 index 000000000000..ef5f348f386a --- /dev/null +++ b/arch/mips/vdso/Makefile @@ -0,0 +1,160 @@ +# Objects to go into the VDSO. +obj-vdso-y := elf.o gettimeofday.o sigreturn.o + +# Common compiler flags between ABIs. +ccflags-vdso := \ + $(filter -I%,$(KBUILD_CFLAGS)) \ + $(filter -E%,$(KBUILD_CFLAGS)) \ + $(filter -march=%,$(KBUILD_CFLAGS)) +cflags-vdso := $(ccflags-vdso) \ + $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ + -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \ + $(call cc-option, -fno-stack-protector) +aflags-vdso := $(ccflags-vdso) \ + $(filter -I%,$(KBUILD_CFLAGS)) \ + $(filter -E%,$(KBUILD_CFLAGS)) \ + -D__ASSEMBLY__ -Wa,-gdwarf-2 + +# +# For the pre-R6 code in arch/mips/vdso/vdso.h for locating +# the base address of VDSO, the linker will emit a R_MIPS_PC32 +# relocation in binutils > 2.25 but it will fail with older versions +# because that relocation is not supported for that symbol. As a result +# of which we are forced to disable the VDSO symbols when building +# with < 2.25 binutils on pre-R6 kernels. For more references on why we +# can't use other methods to get the base address of VDSO please refer to +# the comments on that file. +# +ifndef CONFIG_CPU_MIPSR6 + ifeq ($(call ld-ifversion, -gt, 22400000, y),) + $(warning MIPS VDSO requires binutils > 2.24) + obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y)) + ccflags-vdso += -DDISABLE_MIPS_VDSO + endif +endif + +# VDSO linker flags. +VDSO_LDFLAGS := \ + -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \ + -nostdlib -shared \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \ + $(call cc-ldoption, -Wl$(comma)--build-id) + +GCOV_PROFILE := n + +# +# Shared build commands. +# + +quiet_cmd_vdsold = VDSO $@ + cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \ + -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@ + +hostprogs-y := genvdso + +quiet_cmd_genvdso = GENVDSO $@ +define cmd_genvdso + cp $< $(<:%.dbg=%) && \ + $(OBJCOPY) -S $< $(<:%.dbg=%) && \ + $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME) +endef + +# +# Build native VDSO. +# + +native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS)) + +targets += $(obj-vdso-y) +targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c + +obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o) + +$(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi) +$(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 + $(call if_changed,vdsold) + +$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE + $(call if_changed,genvdso) + +obj-y += vdso-image.o + +# +# Build O32 VDSO. +# + +# 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 + +ifdef CONFIG_MIPS32_O32 + +obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o) + +$(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32 +$(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32 + +$(obj)/%-o32.o: $(src)/%.S FORCE + $(call if_changed_dep,as_o_S) + +$(obj)/%-o32.o: $(src)/%.c FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + +$(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 + $(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 + $(call if_changed,genvdso) + +obj-y += vdso-o32-image.o + +endif + +# +# Build N32 VDSO. +# + +targets += $(obj-vdso-y:%.o=%-n32.o) +targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c + +ifdef CONFIG_MIPS32_N32 + +obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o) + +$(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32 +$(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32 + +$(obj)/%-n32.o: $(src)/%.S FORCE + $(call if_changed_dep,as_o_S) + +$(obj)/%-n32.o: $(src)/%.c FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + +$(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 + $(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 + $(call if_changed,genvdso) + +obj-y += vdso-n32-image.o + +endif + +# FIXME: Need install rule for debug. +# Needs to deal with dependency for generation of dbg by cmd_genvdso... diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S new file mode 100644 index 000000000000..be37bbb1f061 --- /dev/null +++ b/arch/mips/vdso/elf.S @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +#include "vdso.h" + +#include +#include + +ELFNOTE_START(Linux, 0, "a") + .long LINUX_VERSION_CODE +ELFNOTE_END + +/* + * The .MIPS.abiflags section must be defined with the FP ABI flags set + * to 'any' to be able to link with both old and new libraries. + * Newer toolchains are capable of automatically generating this, but we want + * to work with older toolchains as well. Therefore, we define the contents of + * this section here (under different names), and then genvdso will patch + * it to have the correct name and type. + * + * We base the .MIPS.abiflags section on preprocessor definitions rather than + * CONFIG_* because we need to match the particular ABI we are building the + * VDSO for. + * + * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking + * for the .MIPS.abiflags section description. + */ + + .section .mips_abiflags, "a" + .align 3 +__mips_abiflags: + .hword 0 /* version */ + .byte __mips /* isa_level */ + + /* isa_rev */ +#ifdef __mips_isa_rev + .byte __mips_isa_rev +#else + .byte 0 +#endif + + /* gpr_size */ +#ifdef __mips64 + .byte 2 /* AFL_REG_64 */ +#else + .byte 1 /* AFL_REG_32 */ +#endif + + /* cpr1_size */ +#if (defined(__mips_isa_rev) && __mips_isa_rev >= 6) || defined(__mips64) + .byte 2 /* AFL_REG_64 */ +#else + .byte 1 /* AFL_REG_32 */ +#endif + + .byte 0 /* cpr2_size (AFL_REG_NONE) */ + .byte 0 /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */ + .word 0 /* isa_ext */ + .word 0 /* ases */ + .word 0 /* flags1 */ + .word 0 /* flags2 */ diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c new file mode 100644 index 000000000000..530a36f465ce --- /dev/null +++ b/arch/mips/vdso/genvdso.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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 tool is used to generate the real VDSO images from the raw image. It + * first patches up the MIPS ABI flags and GNU attributes sections defined in + * elf.S to have the correct name and type. It then generates a C source file + * to be compiled into the kernel containing the VDSO image data and a + * mips_vdso_image struct for it, including symbol offsets extracted from the + * image. + * + * We need to be passed both a stripped and unstripped VDSO image. The stripped + * image is compiled into the kernel, but we must also patch up the unstripped + * image's ABI flags sections so that it can be installed and used for + * debugging. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define these in case the system elf.h is not new enough to have them. */ +#ifndef SHT_GNU_ATTRIBUTES +# define SHT_GNU_ATTRIBUTES 0x6ffffff5 +#endif +#ifndef SHT_MIPS_ABIFLAGS +# define SHT_MIPS_ABIFLAGS 0x7000002a +#endif + +enum { + ABI_O32 = (1 << 0), + ABI_N32 = (1 << 1), + ABI_N64 = (1 << 2), + + ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64, +}; + +/* Symbols the kernel requires offsets for. */ +static struct { + const char *name; + const char *offset_name; + unsigned int abis; +} vdso_symbols[] = { + { "__vdso_sigreturn", "off_sigreturn", ABI_O32 }, + { "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL }, + {} +}; + +static const char *program_name; +static const char *vdso_name; +static unsigned char elf_class; +static unsigned int elf_abi; +static bool need_swap; +static FILE *out_file; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define HOST_ORDER ELFDATA2LSB +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define HOST_ORDER ELFDATA2MSB +#endif + +#define BUILD_SWAP(bits) \ + static uint##bits##_t swap_uint##bits(uint##bits##_t val) \ + { \ + return need_swap ? bswap_##bits(val) : val; \ + } + +BUILD_SWAP(16) +BUILD_SWAP(32) +BUILD_SWAP(64) + +#define __FUNC(name, bits) name##bits +#define _FUNC(name, bits) __FUNC(name, bits) +#define FUNC(name) _FUNC(name, ELF_BITS) + +#define __ELF(x, bits) Elf##bits##_##x +#define _ELF(x, bits) __ELF(x, bits) +#define ELF(x) _ELF(x, ELF_BITS) + +/* + * Include genvdso.h twice with ELF_BITS defined differently to get functions + * for both ELF32 and ELF64. + */ + +#define ELF_BITS 64 +#include "genvdso.h" +#undef ELF_BITS + +#define ELF_BITS 32 +#include "genvdso.h" +#undef ELF_BITS + +static void *map_vdso(const char *path, size_t *_size) +{ + int fd; + struct stat stat; + void *addr; + const Elf32_Ehdr *ehdr; + + fd = open(path, O_RDWR); + if (fd < 0) { + fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name, + path, strerror(errno)); + return NULL; + } + + if (fstat(fd, &stat) != 0) { + fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name, + path, strerror(errno)); + return NULL; + } + + addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + 0); + if (addr == MAP_FAILED) { + fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name, + path, strerror(errno)); + return NULL; + } + + /* ELF32/64 header formats are the same for the bits we're checking. */ + ehdr = addr; + + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { + fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name, + path); + return NULL; + } + + elf_class = ehdr->e_ident[EI_CLASS]; + switch (elf_class) { + case ELFCLASS32: + case ELFCLASS64: + break; + default: + fprintf(stderr, "%s: '%s' has invalid ELF class\n", + program_name, path); + return NULL; + } + + switch (ehdr->e_ident[EI_DATA]) { + case ELFDATA2LSB: + case ELFDATA2MSB: + need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER; + break; + default: + fprintf(stderr, "%s: '%s' has invalid ELF data order\n", + program_name, path); + return NULL; + } + + if (swap_uint16(ehdr->e_machine) != EM_MIPS) { + fprintf(stderr, + "%s: '%s' has invalid ELF machine (expected EM_MIPS)\n", + program_name, path); + return NULL; + } else if (swap_uint16(ehdr->e_type) != ET_DYN) { + fprintf(stderr, + "%s: '%s' has invalid ELF type (expected ET_DYN)\n", + program_name, path); + return NULL; + } + + *_size = stat.st_size; + return addr; +} + +static bool patch_vdso(const char *path, void *vdso) +{ + if (elf_class == ELFCLASS64) + return patch_vdso64(path, vdso); + else + return patch_vdso32(path, vdso); +} + +static bool get_symbols(const char *path, void *vdso) +{ + if (elf_class == ELFCLASS64) + return get_symbols64(path, vdso); + else + return get_symbols32(path, vdso); +} + +int main(int argc, char **argv) +{ + const char *dbg_vdso_path, *vdso_path, *out_path; + void *dbg_vdso, *vdso; + size_t dbg_vdso_size, vdso_size, i; + + program_name = argv[0]; + + if (argc < 4 || argc > 5) { + fprintf(stderr, + "Usage: %s []\n", + program_name); + return EXIT_FAILURE; + } + + dbg_vdso_path = argv[1]; + vdso_path = argv[2]; + out_path = argv[3]; + vdso_name = (argc > 4) ? argv[4] : ""; + + dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size); + if (!dbg_vdso) + return EXIT_FAILURE; + + vdso = map_vdso(vdso_path, &vdso_size); + if (!vdso) + return EXIT_FAILURE; + + /* Patch both the VDSOs' ABI flags sections. */ + if (!patch_vdso(dbg_vdso_path, dbg_vdso)) + return EXIT_FAILURE; + if (!patch_vdso(vdso_path, vdso)) + return EXIT_FAILURE; + + if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) { + fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name, + dbg_vdso_path, strerror(errno)); + return EXIT_FAILURE; + } else if (msync(vdso, vdso_size, MS_SYNC) != 0) { + fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name, + vdso_path, strerror(errno)); + return EXIT_FAILURE; + } + + out_file = fopen(out_path, "w"); + if (!out_file) { + fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name, + out_path, strerror(errno)); + return EXIT_FAILURE; + } + + fprintf(out_file, "/* Automatically generated - do not edit */\n"); + fprintf(out_file, "#include \n"); + fprintf(out_file, "#include \n"); + fprintf(out_file, "#include \n"); + + /* Write out the stripped VDSO data. */ + fprintf(out_file, + "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t", + vdso_size); + for (i = 0; i < vdso_size; i++) { + if (!(i % 10)) + fprintf(out_file, "\n\t"); + fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]); + } + fprintf(out_file, "\n};\n"); + + /* Preallocate a page array. */ + fprintf(out_file, + "static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n", + vdso_size); + + fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n", + (vdso_name[0]) ? "_" : "", vdso_name); + fprintf(out_file, "\t.data = vdso_data,\n"); + fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size); + fprintf(out_file, "\t.mapping = {\n"); + fprintf(out_file, "\t\t.name = \"[vdso]\",\n"); + fprintf(out_file, "\t\t.pages = vdso_pages,\n"); + fprintf(out_file, "\t},\n"); + + /* Calculate and write symbol offsets to */ + if (!get_symbols(dbg_vdso_path, dbg_vdso)) { + unlink(out_path); + return EXIT_FAILURE; + } + + fprintf(out_file, "};\n"); + + return EXIT_SUCCESS; +} diff --git a/arch/mips/vdso/genvdso.h b/arch/mips/vdso/genvdso.h new file mode 100644 index 000000000000..94334727059a --- /dev/null +++ b/arch/mips/vdso/genvdso.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +static inline bool FUNC(patch_vdso)(const char *path, void *vdso) +{ + const ELF(Ehdr) *ehdr = vdso; + void *shdrs; + ELF(Shdr) *shdr; + char *shstrtab, *name; + uint16_t sh_count, sh_entsize, i; + unsigned int local_gotno, symtabno, gotsym; + ELF(Dyn) *dyn = NULL; + + shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); + sh_count = swap_uint16(ehdr->e_shnum); + sh_entsize = swap_uint16(ehdr->e_shentsize); + + shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx)); + shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset); + + for (i = 0; i < sh_count; i++) { + shdr = shdrs + (i * sh_entsize); + name = shstrtab + swap_uint32(shdr->sh_name); + + /* + * Ensure there are no relocation sections - ld.so does not + * relocate the VDSO so if there are relocations things will + * break. + */ + switch (swap_uint32(shdr->sh_type)) { + case SHT_REL: + case SHT_RELA: + fprintf(stderr, + "%s: '%s' contains relocation sections\n", + program_name, path); + return false; + case SHT_DYNAMIC: + dyn = vdso + FUNC(swap_uint)(shdr->sh_offset); + break; + } + + /* Check for existing sections. */ + if (strcmp(name, ".MIPS.abiflags") == 0) { + fprintf(stderr, + "%s: '%s' already contains a '.MIPS.abiflags' section\n", + program_name, path); + return false; + } + + if (strcmp(name, ".mips_abiflags") == 0) { + strcpy(name, ".MIPS.abiflags"); + shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS); + shdr->sh_entsize = shdr->sh_size; + } + } + + /* + * Ensure the GOT has no entries other than the standard 2, for the same + * reason we check that there's no relocation sections above. + * The standard two entries are: + * - Lazy resolver + * - Module pointer + */ + if (dyn) { + local_gotno = symtabno = gotsym = 0; + + while (FUNC(swap_uint)(dyn->d_tag) != DT_NULL) { + switch (FUNC(swap_uint)(dyn->d_tag)) { + /* + * This member holds the number of local GOT entries. + */ + case DT_MIPS_LOCAL_GOTNO: + local_gotno = FUNC(swap_uint)(dyn->d_un.d_val); + break; + /* + * This member holds the number of entries in the + * .dynsym section. + */ + case DT_MIPS_SYMTABNO: + symtabno = FUNC(swap_uint)(dyn->d_un.d_val); + break; + /* + * This member holds the index of the first dynamic + * symbol table entry that corresponds to an entry in + * the GOT. + */ + case DT_MIPS_GOTSYM: + gotsym = FUNC(swap_uint)(dyn->d_un.d_val); + break; + } + + dyn++; + } + + if (local_gotno > 2 || symtabno - gotsym) { + fprintf(stderr, + "%s: '%s' contains unexpected GOT entries\n", + program_name, path); + return false; + } + } + + return true; +} + +static inline bool FUNC(get_symbols)(const char *path, void *vdso) +{ + const ELF(Ehdr) *ehdr = vdso; + void *shdrs, *symtab; + ELF(Shdr) *shdr; + const ELF(Sym) *sym; + char *strtab, *name; + uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j; + uint64_t offset; + uint32_t flags; + + shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); + sh_count = swap_uint16(ehdr->e_shnum); + sh_entsize = swap_uint16(ehdr->e_shentsize); + + for (i = 0; i < sh_count; i++) { + shdr = shdrs + (i * sh_entsize); + + if (swap_uint32(shdr->sh_type) == SHT_SYMTAB) + break; + } + + if (i == sh_count) { + fprintf(stderr, "%s: '%s' has no symbol table\n", program_name, + path); + return false; + } + + /* Get flags */ + flags = swap_uint32(ehdr->e_flags); + if (elf_class == ELFCLASS64) + elf_abi = ABI_N64; + else if (flags & EF_MIPS_ABI2) + elf_abi = ABI_N32; + else + elf_abi = ABI_O32; + + /* Get symbol table. */ + symtab = vdso + FUNC(swap_uint)(shdr->sh_offset); + st_entsize = FUNC(swap_uint)(shdr->sh_entsize); + st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize; + + /* Get string table. */ + shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize); + strtab = vdso + FUNC(swap_uint)(shdr->sh_offset); + + /* Write offsets for symbols needed by the kernel. */ + for (i = 0; vdso_symbols[i].name; i++) { + if (!(vdso_symbols[i].abis & elf_abi)) + continue; + + for (j = 0; j < st_count; j++) { + sym = symtab + (j * st_entsize); + name = strtab + swap_uint32(sym->st_name); + + if (!strcmp(name, vdso_symbols[i].name)) { + offset = FUNC(swap_uint)(sym->st_value); + + fprintf(out_file, + "\t.%s = 0x%" PRIx64 ",\n", + vdso_symbols[i].offset_name, offset); + break; + } + } + + if (j == st_count) { + fprintf(stderr, + "%s: '%s' is missing required symbol '%s'\n", + program_name, path, vdso_symbols[i].name); + return false; + } + } + + return true; +} diff --git a/arch/mips/vdso/sigreturn.S b/arch/mips/vdso/sigreturn.S new file mode 100644 index 000000000000..715bf5993529 --- /dev/null +++ b/arch/mips/vdso/sigreturn.S @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +#include "vdso.h" + +#include + +#include +#include + + .section .text + .cfi_sections .debug_frame + +LEAF(__vdso_rt_sigreturn) + .cfi_startproc + .frame sp, 0, ra + .mask 0x00000000, 0 + .fmask 0x00000000, 0 + .cfi_signal_frame + + li v0, __NR_rt_sigreturn + syscall + + .cfi_endproc + END(__vdso_rt_sigreturn) + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +LEAF(__vdso_sigreturn) + .cfi_startproc + .frame sp, 0, ra + .mask 0x00000000, 0 + .fmask 0x00000000, 0 + .cfi_signal_frame + + li v0, __NR_sigreturn + syscall + + .cfi_endproc + END(__vdso_sigreturn) + +#endif diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h new file mode 100644 index 000000000000..0bb6b1adc385 --- /dev/null +++ b/arch/mips/vdso/vdso.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +#include + +#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT) + +/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */ +#undef CONFIG_64BIT +#define CONFIG_32BIT 1 +#ifndef __ASSEMBLY__ +#include +#endif +#endif + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +static inline unsigned long get_vdso_base(void) +{ + unsigned long addr; + + /* + * We can't use cpu_has_mips_r6 since it needs the cpu_data[] + * kernel symbol. + */ +#ifdef CONFIG_CPU_MIPSR6 + /* + * lapc is an alias to addiupc reg, - . + * + * We can't use addiupc because there is no label-label + * support for the addiupc reloc + */ + __asm__("lapc %0, _start \n" + : "=r" (addr) : :); +#else + /* + * Get the base load address of the VDSO. We have to avoid generating + * relocations and references to the GOT because ld.so does not peform + * relocations on the VDSO. We use the current offset from the VDSO base + * and perform a PC-relative branch which gives the absolute address in + * ra, and take the difference. The assembler chokes on + * "li %0, _start - .", so embed the offset as a word and branch over + * it. + * + */ + + __asm__( + " .set push \n" + " .set noreorder \n" + " bal 1f \n" + " nop \n" + " .word _start - . \n" + "1: lw %0, 0($31) \n" + " " STR(PTR_ADDU) " %0, $31, %0 \n" + " .set pop \n" + : "=r" (addr) + : + : "$31"); +#endif /* CONFIG_CPU_MIPSR6 */ + + return addr; +} + +static inline const union mips_vdso_data *get_vdso_data(void) +{ + return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE); +} + +#endif /* __ASSEMBLY__ */ diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S new file mode 100644 index 000000000000..21655b6fefc5 --- /dev/null +++ b/arch/mips/vdso/vdso.lds.S @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI64 +OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips") +#elif _MIPS_SIM == _MIPS_SIM_NABI32 +OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips") +#else +OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") +#endif + +OUTPUT_ARCH(mips) + +SECTIONS +{ + PROVIDE(_start = .); + . = SIZEOF_HEADERS; + + /* + * In order to retain compatibility with older toolchains we provide the + * ABI flags section ourself. Newer assemblers will automatically + * generate .MIPS.abiflags sections so we discard such input sections, + * and then manually define our own section here. genvdso will patch + * this section to have the correct name/type. + */ + .mips_abiflags : { *(.mips_abiflags) } :text :abiflags + + .reginfo : { *(.reginfo) } :text :reginfo + + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + .text : { *(.text*) } :text + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + + .dynamic : { *(.dynamic) } :text :dynamic + + .rodata : { *(.rodata*) } :text + + _end = .; + PROVIDE(end = .); + + /DISCARD/ : { + *(.MIPS.abiflags) + *(.gnu.attributes) + *(.note.GNU-stack) + *(.data .data.* .gnu.linkonce.d.* .sdata*) + *(.bss .sbss .dynbss .dynsbss) + } +} + +PHDRS +{ + /* + * Provide a PT_MIPS_ABIFLAGS header to assign the ABI flags section + * to. We can specify the header type directly here so no modification + * is needed later on. + */ + abiflags 0x70000003; + + /* + * The ABI flags header must exist directly after the PT_INTERP header, + * so we must explicitly place the PT_MIPS_REGINFO header after it to + * stop the linker putting one in at the start. + */ + reginfo 0x70000000; + + text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr PT_GNU_EH_FRAME; +} + +VERSION +{ + LINUX_2.6 { + local: *; + }; +} From c0a9f72c156baf1e88c33c6ba4450647af1b8804 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 12 Oct 2015 10:40:43 +0100 Subject: [PATCH 063/120] irqchip: irq-mips-gic: Provide function to map GIC user section The GIC provides a "user-mode visible" section containing a mirror of the counter registers which can be mapped into user memory. This will be used by the VDSO time function implementations, so provide a function to map it in. When the GIC is not enabled in Kconfig a dummy inline version of this function is provided, along with "#define gic_present 0", so that we don't have to litter the VDSO code with ifdefs. [markos.chandras@imgtec.com: - Move mapping code to arch/mips/kernel/vdso.c and use a resource type to get the GIC usermode information - Avoid renaming function arguments and use __gic_base_addr to hold the base GIC address prior to ioremap.] [ralf@linux-mips.org: Fix up gic_get_usm_range() to compile and make inline again.] Signed-off-by: Alex Smith Signed-off-by: Markos Chandras Reviewed-by: Marc Zyngier Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier Cc: Alex Smith Cc: Markos Chandras Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/11281/ Signed-off-by: Ralf Baechle --- drivers/irqchip/irq-mips-gic.c | 14 ++++++++++++++ include/linux/irqchip/mips-gic.h | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index aeaa061f0dbf..9e17ef27a183 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -29,6 +29,7 @@ struct gic_pcpu_mask { DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS); }; +static unsigned long __gic_base_addr; static void __iomem *gic_base; static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; static DEFINE_SPINLOCK(gic_lock); @@ -301,6 +302,17 @@ int gic_get_c0_fdc_int(void) GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); } +int gic_get_usm_range(struct resource *gic_usm_res) +{ + if (!gic_present) + return -1; + + gic_usm_res->start = __gic_base_addr + USM_VISIBLE_SECTION_OFS; + gic_usm_res->end = gic_usm_res->start + (USM_VISIBLE_SECTION_SIZE - 1); + + return 0; +} + static void gic_handle_shared_int(bool chained) { unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4; @@ -798,6 +810,8 @@ static void __init __gic_init(unsigned long gic_base_addr, { unsigned int gicconfig; + __gic_base_addr = gic_base_addr; + gic_base = ioremap_nocache(gic_base_addr, gic_addrspace_size); gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG)); diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h index 4e6861605050..ce824db48d64 100644 --- a/include/linux/irqchip/mips-gic.h +++ b/include/linux/irqchip/mips-gic.h @@ -9,6 +9,7 @@ #define __LINUX_IRQCHIP_MIPS_GIC_H #include +#include #define GIC_MAX_INTRS 256 @@ -245,6 +246,8 @@ #define GIC_SHARED_TO_HWIRQ(x) (GIC_SHARED_HWIRQ_BASE + (x)) #define GIC_HWIRQ_TO_SHARED(x) ((x) - GIC_SHARED_HWIRQ_BASE) +#ifdef CONFIG_MIPS_GIC + extern unsigned int gic_present; extern void gic_init(unsigned long gic_base_addr, @@ -264,4 +267,18 @@ extern unsigned int plat_ipi_resched_int_xlate(unsigned int); extern int gic_get_c0_compare_int(void); extern int gic_get_c0_perfcount_int(void); extern int gic_get_c0_fdc_int(void); +extern int gic_get_usm_range(struct resource *gic_usm_res); + +#else /* CONFIG_MIPS_GIC */ + +#define gic_present 0 + +static inline int gic_get_usm_range(struct resource *gic_usm_res) +{ + /* Shouldn't be called. */ + return -1; +} + +#endif /* CONFIG_MIPS_GIC */ + #endif /* __LINUX_IRQCHIP_MIPS_GIC_H */ From a7f4df4e21dd8a8dab96e88acd2c9c5017b83fc6 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 21 Oct 2015 09:57:44 +0100 Subject: [PATCH 064/120] MIPS: VDSO: Add implementations of gettimeofday() and clock_gettime() Add user-mode implementations of gettimeofday() and clock_gettime() to the VDSO. This is currently usable with 2 clocksources: the CP0 count register, which is accessible to user-mode via RDHWR on R2 and later cores, or the MIPS Global Interrupt Controller (GIC) timer, which provides a "user-mode visible" section containing a mirror of its counter registers. This section must be mapped into user memory, which is done below the VDSO data page. When a supported clocksource is not in use, the VDSO functions will return -ENOSYS, which causes libc to fall back on the standard syscall path. When support for neither of these clocksources is compiled into the kernel at all, the VDSO still provides clock_gettime(), as the coarse realtime/monotonic clocks can still be implemented. However, gettimeofday() is not provided in this case as nothing can be done without a suitable clocksource. This causes the symbol lookup to fail in libc and it will then always use the standard syscall path. This patch includes a workaround for a bug in QEMU which results in RDHWR on the CP0 count register always returning a constant (incorrect) value. A fix for this has been submitted, and the workaround can be removed after the fix has been in stable releases for a reasonable amount of time. A simple performance test which calls gettimeofday() 1000 times in a loop and calculates the average execution time gives the following results on a Malta + I6400 (running at 20MHz): - Syscall: ~31000 ns - VDSO (GIC): ~15000 ns - VDSO (CP0): ~9500 ns [markos.chandras@imgtec.com: - Minor code re-arrangements in order for mappings to be made in the order they appear to the process' address space. - Move do_{monotonic, realtime} outside of the MIPS_CLOCK_VSYSCALL ifdef - Use gic_get_usm_range so we can do the GIC mapping in the arch/mips/kernel/vdso instead of the GIC irqchip driver] Signed-off-by: Alex Smith Signed-off-by: Markos Chandras Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11338/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 5 + arch/mips/include/asm/clocksource.h | 29 ++++ arch/mips/include/asm/vdso.h | 68 +++++++- arch/mips/kernel/csrc-r4k.c | 44 +++++ arch/mips/kernel/vdso.c | 71 +++++++- arch/mips/vdso/gettimeofday.c | 232 +++++++++++++++++++++++++++ arch/mips/vdso/vdso.h | 9 ++ arch/mips/vdso/vdso.lds.S | 5 + drivers/clocksource/mips-gic-timer.c | 7 +- 9 files changed, 460 insertions(+), 10 deletions(-) create mode 100644 arch/mips/include/asm/clocksource.h create mode 100644 arch/mips/vdso/gettimeofday.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 9322d267e774..2f45c866e7ca 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -61,6 +61,8 @@ config MIPS select SYSCTL_EXCEPTION_TRACE select HAVE_VIRT_CPU_ACCOUNTING_GEN select HAVE_IRQ_TIME_ACCOUNTING + select GENERIC_TIME_VSYSCALL + select ARCH_CLOCKSOURCE_DATA menu "Machine selection" @@ -1040,6 +1042,9 @@ config CSRC_R4K config CSRC_SB1250 bool +config MIPS_CLOCK_VSYSCALL + def_bool CSRC_R4K || CLKSRC_MIPS_GIC + config GPIO_TXX9 select ARCH_REQUIRE_GPIOLIB bool diff --git a/arch/mips/include/asm/clocksource.h b/arch/mips/include/asm/clocksource.h new file mode 100644 index 000000000000..3deb1d0c1a94 --- /dev/null +++ b/arch/mips/include/asm/clocksource.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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_CLOCKSOURCE_H +#define __ASM_CLOCKSOURCE_H + +#include + +/* VDSO clocksources. */ +#define VDSO_CLOCK_NONE 0 /* No suitable clocksource. */ +#define VDSO_CLOCK_R4K 1 /* Use the coprocessor 0 count. */ +#define VDSO_CLOCK_GIC 2 /* Use the GIC. */ + +/** + * struct arch_clocksource_data - Architecture-specific clocksource information. + * @vdso_clock_mode: Method the VDSO should use to access the clocksource. + */ +struct arch_clocksource_data { + u8 vdso_clock_mode; +}; + +#endif /* __ASM_CLOCKSOURCE_H */ diff --git a/arch/mips/include/asm/vdso.h b/arch/mips/include/asm/vdso.h index db2d45be8f2e..8f4ca5dd992b 100644 --- a/arch/mips/include/asm/vdso.h +++ b/arch/mips/include/asm/vdso.h @@ -13,6 +13,8 @@ #include +#include + /** * struct mips_vdso_image - Details of a VDSO image. * @data: Pointer to VDSO image data (page-aligned). @@ -53,18 +55,82 @@ extern struct mips_vdso_image vdso_image_n32; /** * union mips_vdso_data - Data provided by the kernel for the VDSO. + * @xtime_sec: Current real time (seconds part). + * @xtime_nsec: Current real time (nanoseconds part, shifted). + * @wall_to_mono_sec: Wall-to-monotonic offset (seconds part). + * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part). + * @seq_count: Counter to synchronise updates (odd = updating). + * @cs_shift: Clocksource shift value. + * @clock_mode: Clocksource to use for time functions. + * @cs_mult: Clocksource multiplier value. + * @cs_cycle_last: Clock cycle value at last update. + * @cs_mask: Clocksource mask value. + * @tz_minuteswest: Minutes west of Greenwich (from timezone). + * @tz_dsttime: Type of DST correction (from timezone). * * This structure contains data needed by functions within the VDSO. It is - * populated by the kernel and mapped read-only into user memory. + * populated by the kernel and mapped read-only into user memory. The time + * fields are mirrors of internal data from the timekeeping infrastructure. * * Note: Care should be taken when modifying as the layout must remain the same * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel). */ union mips_vdso_data { struct { + u64 xtime_sec; + u64 xtime_nsec; + u32 wall_to_mono_sec; + u32 wall_to_mono_nsec; + u32 seq_count; + u32 cs_shift; + u8 clock_mode; + u32 cs_mult; + u64 cs_cycle_last; + u64 cs_mask; + s32 tz_minuteswest; + s32 tz_dsttime; }; u8 page[PAGE_SIZE]; }; +static inline u32 vdso_data_read_begin(const union mips_vdso_data *data) +{ + u32 seq; + + while (true) { + seq = ACCESS_ONCE(data->seq_count); + if (likely(!(seq & 1))) { + /* Paired with smp_wmb() in vdso_data_write_*(). */ + smp_rmb(); + return seq; + } + + cpu_relax(); + } +} + +static inline bool vdso_data_read_retry(const union mips_vdso_data *data, + u32 start_seq) +{ + /* Paired with smp_wmb() in vdso_data_write_*(). */ + smp_rmb(); + return unlikely(data->seq_count != start_seq); +} + +static inline void vdso_data_write_begin(union mips_vdso_data *data) +{ + ++data->seq_count; + + /* Ensure sequence update is written before other data page values. */ + smp_wmb(); +} + +static inline void vdso_data_write_end(union mips_vdso_data *data) +{ + /* Ensure data values are written before updating sequence again. */ + smp_wmb(); + ++data->seq_count; +} + #endif /* __ASM_VDSO_H */ diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index e5ed7ada1433..1f910563fdf6 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c @@ -28,6 +28,43 @@ static u64 notrace r4k_read_sched_clock(void) return read_c0_count(); } +static inline unsigned int rdhwr_count(void) +{ + unsigned int count; + + __asm__ __volatile__( + " .set push\n" + " .set mips32r2\n" + " rdhwr %0, $2\n" + " .set pop\n" + : "=r" (count)); + + return count; +} + +static bool rdhwr_count_usable(void) +{ + unsigned int prev, curr, i; + + /* + * Older QEMUs have a broken implementation of RDHWR for the CP0 count + * which always returns a constant value. Try to identify this and don't + * use it in the VDSO if it is broken. This workaround can be removed + * once the fix has been in QEMU stable for a reasonable amount of time. + */ + for (i = 0, prev = rdhwr_count(); i < 100; i++) { + curr = rdhwr_count(); + + if (curr != prev) + return true; + + prev = curr; + } + + pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n"); + return false; +} + int __init init_r4k_clocksource(void) { if (!cpu_has_counter || !mips_hpt_frequency) @@ -36,6 +73,13 @@ int __init init_r4k_clocksource(void) /* Calculate a somewhat reasonable rating value */ clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; + /* + * R2 onwards makes the count accessible to user mode so it can be used + * by the VDSO (HWREna is configured by configure_hwrena()). + */ + if (cpu_has_mips_r2_r6 && rdhwr_count_usable()) + clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K; + clocksource_register_hz(&clocksource_mips, mips_hpt_frequency); sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency); diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 56cc3c4377fb..975e99759bab 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -12,9 +12,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include @@ -23,7 +26,7 @@ static union mips_vdso_data vdso_data __page_aligned_data; /* - * Mapping for the VDSO data pages. The real pages are mapped manually, as + * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as * what we map and where within the area they are mapped is determined at * runtime. */ @@ -64,25 +67,67 @@ static int __init init_vdso(void) } subsys_initcall(init_vdso); +void update_vsyscall(struct timekeeper *tk) +{ + vdso_data_write_begin(&vdso_data); + + vdso_data.xtime_sec = tk->xtime_sec; + vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec; + vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec; + vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec; + vdso_data.cs_shift = tk->tkr_mono.shift; + + vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode; + if (vdso_data.clock_mode != VDSO_CLOCK_NONE) { + vdso_data.cs_mult = tk->tkr_mono.mult; + vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last; + vdso_data.cs_mask = tk->tkr_mono.mask; + } + + vdso_data_write_end(&vdso_data); +} + +void update_vsyscall_tz(void) +{ + if (vdso_data.clock_mode != VDSO_CLOCK_NONE) { + vdso_data.tz_minuteswest = sys_tz.tz_minuteswest; + vdso_data.tz_dsttime = sys_tz.tz_dsttime; + } +} + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mips_vdso_image *image = current->thread.abi->vdso; struct mm_struct *mm = current->mm; - unsigned long base, vdso_addr; + unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr; struct vm_area_struct *vma; + struct resource gic_res; int ret; down_write(&mm->mmap_sem); - base = get_unmapped_area(NULL, 0, PAGE_SIZE + image->size, 0, 0); + /* + * Determine total area size. This includes the VDSO data itself, the + * data page, and the GIC user page if present. Always create a mapping + * for the GIC user area if the GIC is present regardless of whether it + * is the current clocksource, in case it comes into use later on. We + * only map a page even though the total area is 64K, as we only need + * the counter registers at the start. + */ + gic_size = gic_present ? PAGE_SIZE : 0; + vvar_size = gic_size + PAGE_SIZE; + size = vvar_size + image->size; + + base = get_unmapped_area(NULL, 0, size, 0, 0); if (IS_ERR_VALUE(base)) { ret = base; goto out; } - vdso_addr = base + PAGE_SIZE; + data_addr = base + gic_size; + vdso_addr = data_addr + PAGE_SIZE; - vma = _install_special_mapping(mm, base, PAGE_SIZE, + vma = _install_special_mapping(mm, base, vvar_size, VM_READ | VM_MAYREAD, &vdso_vvar_mapping); if (IS_ERR(vma)) { @@ -90,8 +135,22 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) goto out; } + /* Map GIC user page. */ + if (gic_size) { + ret = gic_get_usm_range(&gic_res); + if (ret) + goto out; + + ret = io_remap_pfn_range(vma, base, + gic_res.start >> PAGE_SHIFT, + gic_size, + pgprot_noncached(PAGE_READONLY)); + if (ret) + goto out; + } + /* Map data page. */ - ret = remap_pfn_range(vma, base, + ret = remap_pfn_range(vma, data_addr, virt_to_phys(&vdso_data) >> PAGE_SHIFT, PAGE_SIZE, PAGE_READONLY); if (ret) diff --git a/arch/mips/vdso/gettimeofday.c b/arch/mips/vdso/gettimeofday.c new file mode 100644 index 000000000000..ce89c9e294f9 --- /dev/null +++ b/arch/mips/vdso/gettimeofday.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Alex Smith + * + * 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. + */ + +#include "vdso.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +static __always_inline int do_realtime_coarse(struct timespec *ts, + const union mips_vdso_data *data) +{ + u32 start_seq; + + do { + start_seq = vdso_data_read_begin(data); + + ts->tv_sec = data->xtime_sec; + ts->tv_nsec = data->xtime_nsec >> data->cs_shift; + } while (vdso_data_read_retry(data, start_seq)); + + return 0; +} + +static __always_inline int do_monotonic_coarse(struct timespec *ts, + const union mips_vdso_data *data) +{ + u32 start_seq; + u32 to_mono_sec; + u32 to_mono_nsec; + + do { + start_seq = vdso_data_read_begin(data); + + ts->tv_sec = data->xtime_sec; + ts->tv_nsec = data->xtime_nsec >> data->cs_shift; + + to_mono_sec = data->wall_to_mono_sec; + to_mono_nsec = data->wall_to_mono_nsec; + } while (vdso_data_read_retry(data, start_seq)); + + ts->tv_sec += to_mono_sec; + timespec_add_ns(ts, to_mono_nsec); + + return 0; +} + +#ifdef CONFIG_CSRC_R4K + +static __always_inline u64 read_r4k_count(void) +{ + unsigned int count; + + __asm__ __volatile__( + " .set push\n" + " .set mips32r2\n" + " rdhwr %0, $2\n" + " .set pop\n" + : "=r" (count)); + + return count; +} + +#endif + +#ifdef CONFIG_CLKSRC_MIPS_GIC + +static __always_inline u64 read_gic_count(const union mips_vdso_data *data) +{ + void __iomem *gic = get_gic(data); + u32 hi, hi2, lo; + + do { + hi = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS); + lo = __raw_readl(gic + GIC_UMV_SH_COUNTER_31_00_OFS); + hi2 = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS); + } while (hi2 != hi); + + return (((u64)hi) << 32) + lo; +} + +#endif + +static __always_inline u64 get_ns(const union mips_vdso_data *data) +{ + u64 cycle_now, delta, nsec; + + switch (data->clock_mode) { +#ifdef CONFIG_CSRC_R4K + case VDSO_CLOCK_R4K: + cycle_now = read_r4k_count(); + break; +#endif +#ifdef CONFIG_CLKSRC_MIPS_GIC + case VDSO_CLOCK_GIC: + cycle_now = read_gic_count(data); + break; +#endif + default: + return 0; + } + + delta = (cycle_now - data->cs_cycle_last) & data->cs_mask; + + nsec = (delta * data->cs_mult) + data->xtime_nsec; + nsec >>= data->cs_shift; + + return nsec; +} + +static __always_inline int do_realtime(struct timespec *ts, + const union mips_vdso_data *data) +{ + u32 start_seq; + u64 ns; + + do { + start_seq = vdso_data_read_begin(data); + + if (data->clock_mode == VDSO_CLOCK_NONE) + return -ENOSYS; + + ts->tv_sec = data->xtime_sec; + ns = get_ns(data); + } while (vdso_data_read_retry(data, start_seq)); + + ts->tv_nsec = 0; + timespec_add_ns(ts, ns); + + return 0; +} + +static __always_inline int do_monotonic(struct timespec *ts, + const union mips_vdso_data *data) +{ + u32 start_seq; + u64 ns; + u32 to_mono_sec; + u32 to_mono_nsec; + + do { + start_seq = vdso_data_read_begin(data); + + if (data->clock_mode == VDSO_CLOCK_NONE) + return -ENOSYS; + + ts->tv_sec = data->xtime_sec; + ns = get_ns(data); + + to_mono_sec = data->wall_to_mono_sec; + to_mono_nsec = data->wall_to_mono_nsec; + } while (vdso_data_read_retry(data, start_seq)); + + ts->tv_sec += to_mono_sec; + ts->tv_nsec = 0; + timespec_add_ns(ts, ns + to_mono_nsec); + + return 0; +} + +#ifdef CONFIG_MIPS_CLOCK_VSYSCALL + +/* + * This is behind the ifdef so that we don't provide the symbol when there's no + * possibility of there being a usable clocksource, because there's nothing we + * can do without it. When libc fails the symbol lookup it should fall back on + * the standard syscall path. + */ +int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + const union mips_vdso_data *data = get_vdso_data(); + struct timespec ts; + int ret; + + ret = do_realtime(&ts, data); + if (ret) + return ret; + + if (tv) { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + } + + if (tz) { + tz->tz_minuteswest = data->tz_minuteswest; + tz->tz_dsttime = data->tz_dsttime; + } + + return 0; +} + +#endif /* CONFIG_CLKSRC_MIPS_GIC */ + +int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts) +{ + const union mips_vdso_data *data = get_vdso_data(); + int ret; + + switch (clkid) { + case CLOCK_REALTIME_COARSE: + ret = do_realtime_coarse(ts, data); + break; + case CLOCK_MONOTONIC_COARSE: + ret = do_monotonic_coarse(ts, data); + break; + case CLOCK_REALTIME: + ret = do_realtime(ts, data); + break; + case CLOCK_MONOTONIC: + ret = do_monotonic(ts, data); + break; + default: + ret = -ENOSYS; + break; + } + + /* If we return -ENOSYS libc should fall back to a syscall. */ + return ret; +} diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h index 0bb6b1adc385..cfb1be441dec 100644 --- a/arch/mips/vdso/vdso.h +++ b/arch/mips/vdso/vdso.h @@ -77,4 +77,13 @@ static inline const union mips_vdso_data *get_vdso_data(void) return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE); } +#ifdef CONFIG_CLKSRC_MIPS_GIC + +static inline void __iomem *get_gic(const union mips_vdso_data *data) +{ + return (void __iomem *)data - PAGE_SIZE; +} + +#endif /* CONFIG_CLKSRC_MIPS_GIC */ + #endif /* __ASSEMBLY__ */ diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S index 21655b6fefc5..8df7dd53e8e0 100644 --- a/arch/mips/vdso/vdso.lds.S +++ b/arch/mips/vdso/vdso.lds.S @@ -95,6 +95,11 @@ PHDRS VERSION { LINUX_2.6 { +#ifndef DISABLE_MIPS_VDSO + global: + __vdso_clock_gettime; + __vdso_gettimeofday; +#endif local: *; }; } diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 02a1945e5093..89d3e4d7900c 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -140,9 +140,10 @@ static cycle_t gic_hpt_read(struct clocksource *cs) } static struct clocksource gic_clocksource = { - .name = "GIC", - .read = gic_hpt_read, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .name = "GIC", + .read = gic_hpt_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .archdata = { .vdso_clock_mode = VDSO_CLOCK_GIC }, }; static void __init __gic_clocksource_init(void) From 972cfd5502cc87d388a6d358eae717ac48ca4817 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 22:24:25 +0100 Subject: [PATCH 065/120] MIPS: pci-rt3883: drop unneeded of_node_get for_each_child_of_node performs an of_node_get on each iteration, so no of_node_get is needed on breaking out of the loop when the device_node structure is saved in another variable. A simplified semantic match that finds this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root; local idexpression child; @@ for_each_child_of_node(root, child) { ... * of_node_get(child) ... break; } // Signed-off-by: Julia Lawall Cc: kernel-janitors@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: Russell King - ARM Linux Cc: Thomas Petazzoni Cc: Andrew Lunn Cc: Bjorn Helgaas Cc: Jason Cooper Patchwork: https://patchwork.linux-mips.org/patch/11357/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-rt3883.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c index ed6732f9aa87..53a42b07008b 100644 --- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c @@ -432,8 +432,7 @@ static int rt3883_pci_probe(struct platform_device *pdev) /* find the interrupt controller child node */ for_each_child_of_node(np, child) { - if (of_get_property(child, "interrupt-controller", NULL) && - of_node_get(child)) { + if (of_get_property(child, "interrupt-controller", NULL)) { rpc->intc_of_node = child; break; } @@ -449,8 +448,7 @@ static int rt3883_pci_probe(struct platform_device *pdev) /* find the PCI host bridge child node */ for_each_child_of_node(np, child) { if (child->type && - of_node_cmp(child->type, "pci") == 0 && - of_node_get(child)) { + of_node_cmp(child->type, "pci") == 0) { rpc->pci_controller.of_node = child; break; } From e1e1611598148e03c6d65e6c23338f4ff2cee71e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Oct 2015 15:39:02 +0300 Subject: [PATCH 066/120] MIPS: Add LATENCYTOP support Add LATENCYTOP support for MIPS. Tested on OCTEON. Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11353/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 4 ++++ arch/mips/kernel/stacktrace.c | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2f45c866e7ca..10feb1520b0c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2759,6 +2759,10 @@ config STACKTRACE_SUPPORT bool default y +config HAVE_LATENCYTOP_SUPPORT + bool + default y + config PGTABLE_LEVELS int default 3 if 64BIT && !PAGE_SIZE_64KB diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 1ba775d24d38..506021f62549 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c @@ -12,14 +12,15 @@ * Save stack-backtrace addresses into a stack_trace buffer: */ static void save_raw_context_stack(struct stack_trace *trace, - unsigned long reg29) + unsigned long reg29, int savesched) { unsigned long *sp = (unsigned long *)reg29; unsigned long addr; while (!kstack_end(sp)) { addr = *sp++; - if (__kernel_text_address(addr)) { + if (__kernel_text_address(addr) && + (savesched || !in_sched_functions(addr))) { if (trace->skip > 0) trace->skip--; else @@ -31,7 +32,7 @@ static void save_raw_context_stack(struct stack_trace *trace, } static void save_context_stack(struct stack_trace *trace, - struct task_struct *tsk, struct pt_regs *regs) + struct task_struct *tsk, struct pt_regs *regs, int savesched) { unsigned long sp = regs->regs[29]; #ifdef CONFIG_KALLSYMS @@ -43,20 +44,22 @@ static void save_context_stack(struct stack_trace *trace, (unsigned long)task_stack_page(tsk); if (stack_page && sp >= stack_page && sp <= stack_page + THREAD_SIZE - 32) - save_raw_context_stack(trace, sp); + save_raw_context_stack(trace, sp, savesched); return; } do { - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = pc; - if (trace->nr_entries >= trace->max_entries) - break; + if (savesched || !in_sched_functions(pc)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = pc; + if (trace->nr_entries >= trace->max_entries) + break; + } pc = unwind_stack(tsk, &sp, pc, &ra); } while (pc); #else - save_raw_context_stack(trace, sp); + save_raw_context_stack(trace, sp, savesched); #endif } @@ -82,6 +85,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) regs->cp0_epc = tsk->thread.reg31; } else prepare_frametrace(regs); - save_context_stack(trace, tsk, regs); + save_context_stack(trace, tsk, regs, tsk == current); } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); From 500fab97c682f3264eb7f96c22575d70cce6b2b4 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 25 Oct 2015 23:21:42 +0100 Subject: [PATCH 067/120] MIPS: lantiq: add clk_round_rate() This adds a basic implementation of clk_round_rate() The clk_round_rate() function is called by multiple drivers and subsystems now and the lantiq clk driver is supposed to export this, but doesn't do so, this causes linking problems like this one: ERROR: "clk_round_rate" [drivers/media/v4l2-core/videodev.ko] undefined! Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: # 4.1+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11358/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/clk.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index 3fc2e6d70c77..a0706fd4ce0a 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -99,6 +99,23 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(clk_set_rate); +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(!clk_good(clk))) + return 0; + if (clk->rates && *clk->rates) { + unsigned long *r = clk->rates; + + while (*r && (*r != rate)) + r++; + if (!*r) { + return clk->rate; + } + } + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + int clk_enable(struct clk *clk) { if (unlikely(!clk_good(clk))) From daa7ce02513d2188fe6f5ff47ce5ef83eb7de739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 25 Oct 2015 22:16:47 +0100 Subject: [PATCH 068/120] MIPS: BCM47xx: Support on-SoC bus in SPROM reading function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support (extract) SPROM on Broadcom ARM devices we should separate SPROM code and make it a separated module. We won't want to export bcm47xx_fill_sprom symbol so we should support SoC SPROM in the standard fallback function and then modify ssb to use it. Signed-off-by: Rafał Miłecki Acked-by: Hauke Mehrtens Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11355/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/sprom.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 2d5c7a7f24bb..e19c1b9b6697 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -610,14 +610,18 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) { char prefix[10]; - if (bus->bustype == SSB_BUSTYPE_PCI) { + 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; - } else { + default: pr_warn("Unable to fill SPROM for given bustype.\n"); return -EINVAL; } From 2f94acde42b70c81129b398c44aa09411974a16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 25 Oct 2015 22:16:48 +0100 Subject: [PATCH 069/120] MIPS: BCM47xx: Fix some WARNINGs pointed in sprom.c by checkpatch.pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are still few left: 1) Most of them about lines over 80 chars (increased readability exception) 2) Wrong parsing of preprocessor macros Signed-off-by: Rafał Miłecki Cc: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/11356/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/sprom.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index e19c1b9b6697..43353db9a6db 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -60,9 +60,9 @@ static int get_nvram_var(const char *prefix, const char *postfix, } #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) \ +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; \ @@ -422,7 +422,10 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, int i; for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { - struct ssb_sprom_core_pwr_info *pwr_info = &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); @@ -470,7 +473,10 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, int i; for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { - struct ssb_sprom_core_pwr_info *pwr_info = &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); @@ -535,10 +541,11 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, 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. */ + * 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]; From d8cfb5037bfc875e6dc8e09e4caceb443c04ff6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 26 Oct 2015 11:13:16 +0100 Subject: [PATCH 070/120] MIPS: BCM47xx: Fetch board info directly in callback function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This drops another symbol dependency between setup.c and sprom.c which will allow us to make SPROM code a separated module (and share it with ARM). Patch tested on Linksys WRT300N V1. Signed-off-by: Rafał Miłecki Cc: Hauke Mehrtens Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11360/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/setup.c | 19 ++++++++++++++++++- arch/mips/bcm47xx/sprom.c | 13 ------------- arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 5 ----- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 17503a05938e..6d38948f0f1e 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -105,11 +105,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv) { char buf[20]; + int len, err; /* Fill boardinfo structure */ memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo)); - bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL); + len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf)); + if (len > 0) { + err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor); + if (err) + pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n", + buf); + } + if (!iv->boardinfo.vendor) + iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; + + len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)); + if (len > 0) { + err = kstrtou16(strim(buf), 0, &iv->boardinfo.type); + if (err) + pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n", + buf); + } memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); bcm47xx_fill_sprom(&iv->sprom, NULL, false); diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 43353db9a6db..a7e569c7968e 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -599,19 +599,6 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, bcm47xx_sprom_fill_auto(sprom, prefix, fallback); } -#ifdef CONFIG_BCM47XX_SSB -void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, - const char *prefix) -{ - nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0, - true); - if (!boardinfo->vendor) - boardinfo->vendor = SSB_BOARDVENDOR_BCM; - - nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true); -} -#endif - #if defined(CONFIG_BCM47XX_SSB) static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) { diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index 1461c10c1c4c..71e4096a2145 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -48,11 +48,6 @@ extern enum bcm47xx_bus_type bcm47xx_bus_type; void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, bool fallback); -#ifdef CONFIG_BCM47XX_SSB -void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, - const char *prefix); -#endif - void bcm47xx_set_system_type(u16 chip_id); #endif /* __ASM_BCM47XX_H */ From cab7b8363ce5413a69817a2275cf12efa0001334 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:30 +0100 Subject: [PATCH 071/120] MIPS: Lantiq: Add locking for PMU register and check status afterwards The PMU register are accessed in a non atomic way and they could be accessed by different threads simultaneously, which could cause problems this patch adds locking around the PMU registers. In addition we now also wait till the PMU is actually deactivated. [ralf@linux-mips.org: Fix spelling mistake in commit message as noticed by Sergei Shtylyov .] Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11381/ Patchwork: https://patchwork.linux-mips.org/patch/11396/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 2b15491de494..2d019c347093 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -4,6 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2011-2012 John Crispin + * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ #include @@ -85,15 +86,19 @@ void __iomem *ltq_ebu_membase; static u32 ifccr = CGU_IFCCR; static u32 pcicr = CGU_PCICR; +static DEFINE_SPINLOCK(g_pmu_lock); + /* legacy function kept alive to ease clkdev transition */ void ltq_pmu_enable(unsigned int module) { - int err = 1000000; + int retry = 1000000; + spin_lock(&g_pmu_lock); pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR); - do {} while (--err && (pmu_r32(PMU_PWDSR) & module)); + do {} while (--retry && (pmu_r32(PMU_PWDSR) & module)); + spin_unlock(&g_pmu_lock); - if (!err) + if (!retry) panic("activating PMU module failed!"); } EXPORT_SYMBOL(ltq_pmu_enable); @@ -101,7 +106,15 @@ EXPORT_SYMBOL(ltq_pmu_enable); /* legacy function kept alive to ease clkdev transition */ void ltq_pmu_disable(unsigned int module) { + int retry = 1000000; + + spin_lock(&g_pmu_lock); pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR); + do {} while (--retry && (!(pmu_r32(PMU_PWDSR) & module))); + spin_unlock(&g_pmu_lock); + + if (!retry) + pr_warn("deactivating PMU module failed!"); } EXPORT_SYMBOL(ltq_pmu_disable); @@ -123,9 +136,11 @@ static int pmu_enable(struct clk *clk) { int retry = 1000000; + spin_lock(&g_pmu_lock); pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits, PWDCR(clk->module)); do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits)); + spin_unlock(&g_pmu_lock); if (!retry) panic("activating PMU module failed!"); @@ -136,8 +151,15 @@ static int pmu_enable(struct clk *clk) /* disable a clock gate */ static void pmu_disable(struct clk *clk) { - pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, - PWDCR(clk->module)); + int retry = 1000000; + + spin_lock(&g_pmu_lock); + pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, PWDCR(clk->module)); + do {} while (--retry && (!(pmu_r32(PWDSR(clk->module)) & clk->bits))); + spin_unlock(&g_pmu_lock); + + if (!retry) + pr_warn("deactivating PMU module failed!"); } /* the pci enable helper */ From 758d2443edd57a44cfebde585a46fabc8f298250 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:31 +0100 Subject: [PATCH 072/120] MIPS: Lantiq: Add support for setting PMU register on AR10 and GRX390 This adds support for setting the PMU register on the AR10 and GRX390. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11382/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 84 ++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 2d019c347093..5d085654aa33 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,16 +20,18 @@ #include "../clk.h" #include "../prom.h" -/* clock control register */ +/* clock control register for legacy */ #define CGU_IFCCR 0x0018 #define CGU_IFCCR_VR9 0x0024 -/* system clock register */ +/* system clock register for legacy */ #define CGU_SYS 0x0010 /* pci control register */ #define CGU_PCICR 0x0034 #define CGU_PCICR_VR9 0x0038 /* ephy configuration register */ #define CGU_EPHY 0x10 + +/* Legacy PMU register for ar9, ase, danube */ /* power control register */ #define PMU_PWDCR 0x1C /* power status register */ @@ -42,6 +45,47 @@ /* power status register */ #define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR)) + +/* PMU register for ar10 and grx390 */ + +/* First register set */ +#define PMU_CLK_SR 0x20 /* status */ +#define PMU_CLK_CR_A 0x24 /* Enable */ +#define PMU_CLK_CR_B 0x28 /* Disable */ +/* Second register set */ +#define PMU_CLK_SR1 0x30 /* status */ +#define PMU_CLK_CR1_A 0x34 /* Enable */ +#define PMU_CLK_CR1_B 0x38 /* Disable */ +/* Third register set */ +#define PMU_ANA_SR 0x40 /* status */ +#define PMU_ANA_CR_A 0x44 /* Enable */ +#define PMU_ANA_CR_B 0x48 /* Disable */ + +/* Status */ +static u32 pmu_clk_sr[] = { + PMU_CLK_SR, + PMU_CLK_SR1, + PMU_ANA_SR, +}; + +/* Enable */ +static u32 pmu_clk_cr_a[] = { + PMU_CLK_CR_A, + PMU_CLK_CR1_A, + PMU_ANA_CR_A, +}; + +/* Disable */ +static u32 pmu_clk_cr_b[] = { + PMU_CLK_CR_B, + PMU_CLK_CR1_B, + PMU_ANA_CR_B, +}; + +#define PWDCR_EN_XRX(x) (pmu_clk_cr_a[(x)]) +#define PWDCR_DIS_XRX(x) (pmu_clk_cr_b[(x)]) +#define PWDSR_XRX(x) (pmu_clk_sr[(x)]) + /* clock gates that we can en/disable */ #define PMU_USB0_P BIT(0) #define PMU_PCI BIT(4) @@ -136,11 +180,20 @@ static int pmu_enable(struct clk *clk) { int retry = 1000000; - spin_lock(&g_pmu_lock); - pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits, - PWDCR(clk->module)); - do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits)); - spin_unlock(&g_pmu_lock); + if (of_machine_is_compatible("lantiq,ar10") + || of_machine_is_compatible("lantiq,grx390")) { + pmu_w32(clk->bits, PWDCR_EN_XRX(clk->module)); + do {} while (--retry && + (!(pmu_r32(PWDSR_XRX(clk->module)) & clk->bits))); + + } else { + spin_lock(&g_pmu_lock); + pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits, + PWDCR(clk->module)); + do {} while (--retry && + (pmu_r32(PWDSR(clk->module)) & clk->bits)); + spin_unlock(&g_pmu_lock); + } if (!retry) panic("activating PMU module failed!"); @@ -153,10 +206,19 @@ static void pmu_disable(struct clk *clk) { int retry = 1000000; - spin_lock(&g_pmu_lock); - pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, PWDCR(clk->module)); - do {} while (--retry && (!(pmu_r32(PWDSR(clk->module)) & clk->bits))); - spin_unlock(&g_pmu_lock); + if (of_machine_is_compatible("lantiq,ar10") + || of_machine_is_compatible("lantiq,grx390")) { + pmu_w32(clk->bits, PWDCR_DIS_XRX(clk->module)); + do {} while (--retry && + (pmu_r32(PWDSR_XRX(clk->module)) & clk->bits)); + } else { + spin_lock(&g_pmu_lock); + pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, + PWDCR(clk->module)); + do {} while (--retry && + (!(pmu_r32(PWDSR(clk->module)) & clk->bits))); + spin_unlock(&g_pmu_lock); + } if (!retry) pr_warn("deactivating PMU module failed!"); From b5a03d0cb32c35f7ca9a042f01c1de14daaeeb11 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:32 +0100 Subject: [PATCH 073/120] MIPS: Lantiq: Rename CGU_SYS_VR9 register This register is also used on other SoCs. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11383/ Patchwork: https://patchwork.linux-mips.org/patch/11397/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/clk.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 8750dc0a1bf6..55fd1508fb11 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -4,6 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2010 John Crispin + * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ #include @@ -25,8 +26,8 @@ static unsigned int ram_clocks[] = { /* legacy xway clock */ #define CGU_SYS 0x10 -/* vr9 clock */ -#define CGU_SYS_VR9 0x0c +/* vr9, ar10/grx390 clock */ +#define CGU_SYS_XRX 0x0c #define CGU_IF_CLK_VR9 0x24 unsigned long ltq_danube_fpi_hz(void) @@ -104,7 +105,7 @@ unsigned long ltq_vr9_cpu_hz(void) unsigned int cpu_sel; unsigned long clk; - cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf; + cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf; switch (cpu_sel) { case 0: @@ -145,7 +146,7 @@ unsigned long ltq_vr9_fpi_hz(void) unsigned long clk; cpu_clk = ltq_vr9_cpu_hz(); - ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3; + ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3; switch (ocp_sel) { case 0: From 18a3af60fcb6c0f2948e4e2922d3fcaeb1d74c64 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:33 +0100 Subject: [PATCH 074/120] MIPS: Lantiq: Fix pp32 clock on vr9 The vendor code uses different clock values for this clock. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11384/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/clk.h | 2 ++ arch/mips/lantiq/xway/clk.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index 77e4bdb1fe8c..101afcbbfece 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -31,10 +31,12 @@ #define CLOCK_240M 240000000 #define CLOCK_250M 250000000 #define CLOCK_266M 266666666 +#define CLOCK_288M 288888888 #define CLOCK_300M 300000000 #define CLOCK_333M 333333333 #define CLOCK_393M 393215332 #define CLOCK_400M 400000000 +#define CLOCK_432M 432000000 #define CLOCK_450M 450000000 #define CLOCK_500M 500000000 #define CLOCK_600M 600000000 diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 55fd1508fb11..d372a600a9ad 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -175,15 +175,18 @@ unsigned long ltq_vr9_fpi_hz(void) unsigned long ltq_vr9_pp32_hz(void) { - unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3; + unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; unsigned long clk; switch (clksys) { + case 0: + clk = CLOCK_500M; + break; case 1: - clk = CLOCK_450M; + clk = CLOCK_432M; break; case 2: - clk = CLOCK_300M; + clk = CLOCK_288M; break; default: clk = CLOCK_500M; From 61e371d8222fe9fd9beb15f94d27aeec58f36a2d Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:34 +0100 Subject: [PATCH 075/120] MIPS: Lantiq: Add clock detection for grx390 and ar10 This add detection of some clocks on the ar10 and grx390. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11385/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/clk.h | 11 +++ arch/mips/lantiq/xway/clk.c | 157 +++++++++++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index 101afcbbfece..7376ce817eda 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -34,12 +34,15 @@ #define CLOCK_288M 288888888 #define CLOCK_300M 300000000 #define CLOCK_333M 333333333 +#define CLOCK_360M 360000000 #define CLOCK_393M 393215332 #define CLOCK_400M 400000000 #define CLOCK_432M 432000000 #define CLOCK_450M 450000000 #define CLOCK_500M 500000000 #define CLOCK_600M 600000000 +#define CLOCK_666M 666666666 +#define CLOCK_720M 720000000 /* clock out speeds */ #define CLOCK_32_768K 32768 @@ -82,4 +85,12 @@ extern unsigned long ltq_vr9_cpu_hz(void); extern unsigned long ltq_vr9_fpi_hz(void); extern unsigned long ltq_vr9_pp32_hz(void); +extern unsigned long ltq_ar10_cpu_hz(void); +extern unsigned long ltq_ar10_fpi_hz(void); +extern unsigned long ltq_ar10_pp32_hz(void); + +extern unsigned long ltq_grx390_cpu_hz(void); +extern unsigned long ltq_grx390_fpi_hz(void); +extern unsigned long ltq_grx390_pp32_hz(void); + #endif diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index d372a600a9ad..80aad3080ef8 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -28,7 +28,7 @@ static unsigned int ram_clocks[] = { /* vr9, ar10/grx390 clock */ #define CGU_SYS_XRX 0x0c -#define CGU_IF_CLK_VR9 0x24 +#define CGU_IF_CLK_AR10 0x24 unsigned long ltq_danube_fpi_hz(void) { @@ -195,3 +195,158 @@ unsigned long ltq_vr9_pp32_hz(void) return clk; } + +unsigned long ltq_ar10_cpu_hz(void) +{ + unsigned int clksys; + int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1; + int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7; + + switch (cpu_fs) { + case 0: + clksys = CLOCK_500M; + break; + case 1: + clksys = CLOCK_600M; + break; + default: + clksys = CLOCK_500M; + break; + } + + switch (freq_div) { + case 0: + return clksys; + case 1: + return clksys >> 1; + case 2: + return clksys >> 2; + default: + return clksys; + } +} + +unsigned long ltq_ar10_fpi_hz(void) +{ + int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf; + + switch (freq_fpi) { + case 1: + return CLOCK_300M; + case 5: + return CLOCK_250M; + case 2: + return CLOCK_150M; + case 6: + return CLOCK_125M; + + default: + return CLOCK_125M; + } +} + +unsigned long ltq_ar10_pp32_hz(void) +{ + unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; + unsigned long clk; + + switch (clksys) { + case 1: + clk = CLOCK_250M; + break; + case 4: + clk = CLOCK_400M; + break; + default: + clk = CLOCK_250M; + break; + } + + return clk; +} + +unsigned long ltq_grx390_cpu_hz(void) +{ + unsigned int clksys; + int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); + int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7); + + switch (cpu_fs) { + case 0: + clksys = CLOCK_600M; + break; + case 1: + clksys = CLOCK_666M; + break; + case 2: + clksys = CLOCK_720M; + break; + default: + clksys = CLOCK_600M; + break; + } + + switch (freq_div) { + case 0: + return clksys; + case 1: + return clksys >> 1; + case 2: + return clksys >> 2; + default: + return clksys; + } +} + +unsigned long ltq_grx390_fpi_hz(void) +{ + /* fpi clock is derived from ddr_clk */ + unsigned int clksys; + int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); + int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7); + switch (cpu_fs) { + case 0: + clksys = CLOCK_600M; + break; + case 1: + clksys = CLOCK_666M; + break; + case 2: + clksys = CLOCK_720M; + break; + default: + clksys = CLOCK_600M; + break; + } + + switch (freq_div) { + case 1: + return clksys >> 1; + case 2: + return clksys >> 2; + default: + return clksys >> 1; + } +} + +unsigned long ltq_grx390_pp32_hz(void) +{ + unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; + unsigned long clk; + + switch (clksys) { + case 1: + clk = CLOCK_250M; + break; + case 2: + clk = CLOCK_432M; + break; + case 4: + clk = CLOCK_400M; + break; + default: + clk = CLOCK_250M; + break; + } + return clk; +} From 95135bfa7ead1becc2879230f72583dde2b71a0c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:35 +0100 Subject: [PATCH 076/120] MIPS: Lantiq: Deactivate most of the devices by default When the SoC starts up most of the devices should be deactivated by the PMU, they should be activated when they get used by their drivers. Some devices should not get deactivate at startup like the serial, register them in a special way. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11386/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 49 +++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 5d085654aa33..0324038f280c 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -286,8 +286,8 @@ static int clkout_enable(struct clk *clk) } /* manage the clock gates via PMU */ -static void clkdev_add_pmu(const char *dev, const char *con, - unsigned int module, unsigned int bits) +static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate, + unsigned int module, unsigned int bits) { struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); @@ -298,6 +298,13 @@ static void clkdev_add_pmu(const char *dev, const char *con, clk->disable = pmu_disable; clk->module = module; clk->bits = bits; + if (deactivate) { + /* + * Disable it during the initialization. Module should enable + * when used + */ + pmu_disable(clk); + } clkdev_add(&clk->cl); } @@ -416,13 +423,13 @@ void __init ltq_soc_init(void) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); /* add our generic xway clocks */ - clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI); - clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0); - clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT); - clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP); - clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA); - clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI); - clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU); + clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI); + clkdev_add_pmu("1e100400.serial", NULL, 0, 0, PMU_ASC0); + clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT); + clkdev_add_pmu("1e100bb0.stp", NULL, 1, 0, PMU_STP); + clkdev_add_pmu("1e104100.dma", NULL, 1, 0, PMU_DMA); + clkdev_add_pmu("1e100800.spi", NULL, 1, 0, PMU_SPI); + clkdev_add_pmu("1e105300.ebu", NULL, 0, 0, PMU_EBU); clkdev_add_clkout(); /* add the soc dependent clocks */ @@ -430,11 +437,11 @@ void __init ltq_soc_init(void) ifccr = CGU_IFCCR_VR9; pcicr = CGU_PCICR_VR9; } else { - clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE); + clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE); } if (!of_machine_is_compatible("lantiq,ase")) { - clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1); + clkdev_add_pmu("1e100c00.serial", NULL, 0, 0, PMU_ASC1); clkdev_add_pci(); } @@ -446,25 +453,25 @@ void __init ltq_soc_init(void) clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M, CLOCK_133M); clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY), - clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY); + clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); } else if (of_machine_is_compatible("lantiq,vr9")) { clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz()); - clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY); - clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK); - clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI); - clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI); - clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL); - clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS); - clkdev_add_pmu("1e108000.eth", NULL, 0, + clkdev_add_pmu("1d900000.pcie", "phy", 1, 1, PMU1_PCIE_PHY); + clkdev_add_pmu("1d900000.pcie", "bus", 1, 0, PMU_PCIE_CLK); + clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI); + clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI); + clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL); + clkdev_add_pmu("1d900000.pcie", "ahb", 1, 0, PMU_AHBM | PMU_AHBS); + clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM | PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | PMU_PPE_QSB | PMU_PPE_TOP); - clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY); + clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); } else if (of_machine_is_compatible("lantiq,ar9")) { clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), ltq_ar9_fpi_hz(), CLOCK_250M); - clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH); + clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); } else { clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), ltq_danube_fpi_hz(), ltq_danube_pp32_hz()); From e182c98a59e3cf9e78d1d20f32d3bd3d1b4c521a Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:36 +0100 Subject: [PATCH 077/120] MIPS: Lantiq: Add PMU bits for USB and SDIO devices This adds the PUM bits for USB and SDIO devices Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11387/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 0324038f280c..9ed7da570bfa 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -88,11 +88,13 @@ static u32 pmu_clk_cr_b[] = { /* clock gates that we can en/disable */ #define PMU_USB0_P BIT(0) +#define PMU_ASE_SDIO BIT(2) /* ASE special */ #define PMU_PCI BIT(4) #define PMU_DMA BIT(5) #define PMU_USB0 BIT(6) #define PMU_ASC0 BIT(7) #define PMU_EPHY BIT(7) /* ase */ +#define PMU_USIF BIT(7) /* from vr9 until grx390 */ #define PMU_SPI BIT(8) #define PMU_DFE BIT(9) #define PMU_EBU BIT(10) @@ -101,6 +103,7 @@ static u32 pmu_clk_cr_b[] = { #define PMU_AHBS BIT(13) /* vr9 */ #define PMU_FPI BIT(14) #define PMU_AHBM BIT(15) +#define PMU_SDIO BIT(16) /* danube, ar9, vr9 */ #define PMU_ASC1 BIT(17) #define PMU_PPE_QSB BIT(18) #define PMU_PPE_SLL01 BIT(19) @@ -452,28 +455,47 @@ void __init ltq_soc_init(void) else clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M, CLOCK_133M); - clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY), + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); + clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); + clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE); + clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY); clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); + clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO); } else if (of_machine_is_compatible("lantiq,vr9")) { clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz()); + clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0 | PMU_AHBM); + clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P); + clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1 | PMU_AHBM); clkdev_add_pmu("1d900000.pcie", "phy", 1, 1, PMU1_PCIE_PHY); clkdev_add_pmu("1d900000.pcie", "bus", 1, 0, PMU_PCIE_CLK); clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI); clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI); clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL); clkdev_add_pmu("1d900000.pcie", "ahb", 1, 0, PMU_AHBM | PMU_AHBS); + + clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM | PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | PMU_PPE_QSB | PMU_PPE_TOP); clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); + clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); } else if (of_machine_is_compatible("lantiq,ar9")) { clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), ltq_ar9_fpi_hz(), CLOCK_250M); + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); + clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); + clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1); + clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P); clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); + clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); } else { clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), ltq_danube_fpi_hz(), ltq_danube_pp32_hz()); + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); + clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); + clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); } } From d0b991e376e6293f1122813f28c63d3c93fdc97b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:37 +0100 Subject: [PATCH 078/120] MIPS: Lantiq: Add pmu bits for ar10 and grx390 Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11388/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 57 ++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 9ed7da570bfa..bf9b95c94027 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -110,6 +110,7 @@ static u32 pmu_clk_cr_b[] = { #define PMU_PPE_TC BIT(21) #define PMU_PPE_EMA BIT(22) #define PMU_PPE_DPLUM BIT(23) +#define PMU_PPE_DP BIT(23) #define PMU_PPE_DPLUS BIT(24) #define PMU_USB1_P BIT(26) #define PMU_USB1 BIT(27) @@ -118,10 +119,27 @@ static u32 pmu_clk_cr_b[] = { #define PMU_GPHY BIT(30) #define PMU_PCIE_CLK BIT(31) -#define PMU1_PCIE_PHY BIT(0) +#define PMU1_PCIE_PHY BIT(0) /* vr9-specific,moved in ar10/grx390 */ #define PMU1_PCIE_CTL BIT(1) #define PMU1_PCIE_PDI BIT(4) #define PMU1_PCIE_MSI BIT(5) +#define PMU1_CKE BIT(6) +#define PMU1_PCIE1_CTL BIT(17) +#define PMU1_PCIE1_PDI BIT(20) +#define PMU1_PCIE1_MSI BIT(21) +#define PMU1_PCIE2_CTL BIT(25) +#define PMU1_PCIE2_PDI BIT(26) +#define PMU1_PCIE2_MSI BIT(27) + +#define PMU_ANALOG_USB0_P BIT(0) +#define PMU_ANALOG_USB1_P BIT(1) +#define PMU_ANALOG_PCIE0_P BIT(8) +#define PMU_ANALOG_PCIE1_P BIT(9) +#define PMU_ANALOG_PCIE2_P BIT(10) +#define PMU_ANALOG_DSL_AFE BIT(16) +#define PMU_ANALOG_DCDC_2V5 BIT(17) +#define PMU_ANALOG_DCDC_1VX BIT(18) +#define PMU_ANALOG_DCDC_1V0 BIT(19) #define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y)) #define pmu_r32(x) ltq_r32(pmu_membase + (x)) @@ -448,6 +466,22 @@ void __init ltq_soc_init(void) clkdev_add_pci(); } + if (of_machine_is_compatible("lantiq,grx390") || + of_machine_is_compatible("lantiq,ar10")) { + clkdev_add_pmu("1e101000.usb", "phy", 1, 2, PMU_ANALOG_USB0_P); + clkdev_add_pmu("1e106000.usb", "phy", 1, 2, PMU_ANALOG_USB1_P); + /* rc 0 */ + clkdev_add_pmu("1d900000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE0_P); + clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI); + clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI); + clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL); + /* rc 1 */ + clkdev_add_pmu("19000000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE1_P); + clkdev_add_pmu("19000000.pcie", "msi", 1, 1, PMU1_PCIE1_MSI); + clkdev_add_pmu("19000000.pcie", "pdi", 1, 1, PMU1_PCIE1_PDI); + clkdev_add_pmu("19000000.pcie", "ctl", 1, 1, PMU1_PCIE1_CTL); + } + if (of_machine_is_compatible("lantiq,ase")) { if (ltq_cgu_r32(CGU_SYS) & (1 << 5)) clkdev_add_static(CLOCK_266M, CLOCK_133M, @@ -461,6 +495,27 @@ void __init ltq_soc_init(void) clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY); clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO); + } else if (of_machine_is_compatible("lantiq,grx390")) { + clkdev_add_static(ltq_grx390_cpu_hz(), ltq_grx390_fpi_hz(), + ltq_grx390_fpi_hz(), ltq_grx390_pp32_hz()); + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); + clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1); + /* rc 2 */ + clkdev_add_pmu("1a800000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE2_P); + clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI); + clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI); + clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL); + clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP); + clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); + } else if (of_machine_is_compatible("lantiq,ar10")) { + clkdev_add_static(ltq_ar10_cpu_hz(), ltq_ar10_fpi_hz(), + ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz()); + clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); + clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1); + clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | + PMU_PPE_DP | PMU_PPE_TC); + clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); + clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); } else if (of_machine_is_compatible("lantiq,vr9")) { clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz()); From eefee024b012df827fd0aebffcd05665d8511a8a Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:38 +0100 Subject: [PATCH 079/120] MIPS: Lantiq: Add support for gphy firmware loading for ar10 and grx390 Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11389/ Patchwork: https://patchwork.linux-mips.org/patch/11398/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/reset.c | 112 ++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index fe68f9ae47c1..12a7d824d0b6 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -4,6 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2010 John Crispin + * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ #include @@ -22,9 +23,6 @@ #include "../prom.h" -#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y)) -#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x)) - /* reset request register */ #define RCU_RST_REQ 0x0010 /* reset status register */ @@ -32,11 +30,29 @@ /* vr9 gphy registers */ #define RCU_GFS_ADD0_XRX200 0x0020 #define RCU_GFS_ADD1_XRX200 0x0068 +/* xRX300 gphy registers */ +#define RCU_GFS_ADD0_XRX300 0x0020 +#define RCU_GFS_ADD1_XRX300 0x0058 +#define RCU_GFS_ADD2_XRX300 0x00AC +/* xRX330 gphy registers */ +#define RCU_GFS_ADD0_XRX330 0x0020 +#define RCU_GFS_ADD1_XRX330 0x0058 +#define RCU_GFS_ADD2_XRX330 0x00AC +#define RCU_GFS_ADD3_XRX330 0x0264 /* reboot bit */ #define RCU_RD_GPHY0_XRX200 BIT(31) #define RCU_RD_SRST BIT(30) #define RCU_RD_GPHY1_XRX200 BIT(29) +/* xRX300 bits */ +#define RCU_RD_GPHY0_XRX300 BIT(31) +#define RCU_RD_GPHY1_XRX300 BIT(29) +#define RCU_RD_GPHY2_XRX300 BIT(28) +/* xRX330 bits */ +#define RCU_RD_GPHY0_XRX330 BIT(31) +#define RCU_RD_GPHY1_XRX330 BIT(29) +#define RCU_RD_GPHY2_XRX330 BIT(28) +#define RCU_RD_GPHY3_XRX330 BIT(10) /* reset cause */ #define RCU_STAT_SHIFT 26 @@ -47,6 +63,26 @@ /* remapped base addr of the reset control unit */ static void __iomem *ltq_rcu_membase; static struct device_node *ltq_rcu_np; +static DEFINE_SPINLOCK(ltq_rcu_lock); + +static void ltq_rcu_w32(uint32_t val, uint32_t reg_off) +{ + ltq_w32(val, ltq_rcu_membase + reg_off); +} + +static uint32_t ltq_rcu_r32(uint32_t reg_off) +{ + return ltq_r32(ltq_rcu_membase + reg_off); +} + +static void ltq_rcu_w32_mask(uint32_t clr, uint32_t set, uint32_t reg_off) +{ + unsigned long flags; + + spin_lock_irqsave(<q_rcu_lock, flags); + ltq_rcu_w32((ltq_rcu_r32(reg_off) & ~(clr)) | (set), reg_off); + spin_unlock_irqrestore(<q_rcu_lock, flags); +} /* This function is used by the watchdog driver */ int ltq_reset_cause(void) @@ -67,15 +103,40 @@ unsigned char ltq_boot_select(void) return RCU_BOOT_SEL(val); } -/* reset / boot a gphy */ -static struct ltq_xrx200_gphy_reset { +struct ltq_gphy_reset { u32 rd; u32 addr; -} xrx200_gphy[] = { +}; + +/* reset / boot a gphy */ +static struct ltq_gphy_reset xrx200_gphy[] = { {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200}, {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200}, }; +/* reset / boot a gphy */ +static struct ltq_gphy_reset xrx300_gphy[] = { + {RCU_RD_GPHY0_XRX300, RCU_GFS_ADD0_XRX300}, + {RCU_RD_GPHY1_XRX300, RCU_GFS_ADD1_XRX300}, + {RCU_RD_GPHY2_XRX300, RCU_GFS_ADD2_XRX300}, +}; + +/* reset / boot a gphy */ +static struct ltq_gphy_reset xrx330_gphy[] = { + {RCU_RD_GPHY0_XRX330, RCU_GFS_ADD0_XRX330}, + {RCU_RD_GPHY1_XRX330, RCU_GFS_ADD1_XRX330}, + {RCU_RD_GPHY2_XRX330, RCU_GFS_ADD2_XRX330}, + {RCU_RD_GPHY3_XRX330, RCU_GFS_ADD3_XRX330}, +}; + +static void xrx200_gphy_boot_addr(struct ltq_gphy_reset *phy_regs, + dma_addr_t dev_addr) +{ + ltq_rcu_w32_mask(0, phy_regs->rd, RCU_RST_REQ); + ltq_rcu_w32(dev_addr, phy_regs->addr); + ltq_rcu_w32_mask(phy_regs->rd, 0, RCU_RST_REQ); +} + /* reset and boot a gphy. these phys only exist on xrx200 SoC */ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr) { @@ -86,23 +147,34 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr) return -EINVAL; } - clk = clk_get_sys("1f203000.rcu", "gphy"); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - clk_enable(clk); - - if (id > 1) { - dev_err(dev, "%u is an invalid gphy id\n", id); - return -EINVAL; + if (of_machine_is_compatible("lantiq,vr9")) { + clk = clk_get_sys("1f203000.rcu", "gphy"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + clk_enable(clk); } + dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr); - ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd, - RCU_RST_REQ); - ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr); - ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd, - RCU_RST_REQ); + if (of_machine_is_compatible("lantiq,vr9")) { + if (id >= ARRAY_SIZE(xrx200_gphy)) { + dev_err(dev, "%u is an invalid gphy id\n", id); + return -EINVAL; + } + xrx200_gphy_boot_addr(&xrx200_gphy[id], dev_addr); + } else if (of_machine_is_compatible("lantiq,ar10")) { + if (id >= ARRAY_SIZE(xrx300_gphy)) { + dev_err(dev, "%u is an invalid gphy id\n", id); + return -EINVAL; + } + xrx200_gphy_boot_addr(&xrx300_gphy[id], dev_addr); + } else if (of_machine_is_compatible("lantiq,grx390")) { + if (id >= ARRAY_SIZE(xrx330_gphy)) { + dev_err(dev, "%u is an invalid gphy id\n", id); + return -EINVAL; + } + xrx200_gphy_boot_addr(&xrx330_gphy[id], dev_addr); + } return 0; } From a5c1aad853a499f2b9f3a74e0d019b2ea8ad5825 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:39 +0100 Subject: [PATCH 080/120] MIPS: Lantiq: Add SoC detection for ar10 and grx390 Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11390/ Patchwork: https://patchwork.linux-mips.org/patch/11399/ Signed-off-by: Ralf Baechle --- .../include/asm/mach-lantiq/xway/lantiq_soc.h | 12 ++++++++ arch/mips/lantiq/xway/prom.c | 28 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) 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 133336b493b6..3ab4e986d76f 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -36,6 +36,16 @@ #define SOC_ID_GRX288_2 0x00D /* v1.2 */ #define SOC_ID_GRX282_2 0x00E /* v1.2 */ +#define SOC_ID_ARX362 0x004 +#define SOC_ID_ARX368 0x005 +#define SOC_ID_ARX382 0x007 +#define SOC_ID_ARX388 0x008 +#define SOC_ID_URX388 0x009 +#define SOC_ID_GRX383 0x010 +#define SOC_ID_GRX369 0x011 +#define SOC_ID_GRX387 0x00F +#define SOC_ID_GRX389 0x012 + /* SoC Types */ #define SOC_TYPE_DANUBE 0x01 #define SOC_TYPE_TWINPASS 0x02 @@ -43,6 +53,8 @@ #define SOC_TYPE_VR9 0x04 /* v1.1 */ #define SOC_TYPE_VR9_2 0x05 /* v1.2 */ #define SOC_TYPE_AMAZON_SE 0x06 +#define SOC_TYPE_AR10 0x07 +#define SOC_TYPE_GRX390 0x08 /* BOOT_SEL - find what boot media we have */ #define BS_EXT_ROM 0x0 diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c index 248429ab2622..2b0386188010 100644 --- a/arch/mips/lantiq/xway/prom.c +++ b/arch/mips/lantiq/xway/prom.c @@ -4,6 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2010 John Crispin + * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ #include @@ -19,8 +20,10 @@ #define SOC_TWINPASS "Twinpass" #define SOC_AMAZON_SE "Amazon_SE" #define SOC_AR9 "AR9" -#define SOC_GR9 "GR9" -#define SOC_VR9 "VR9" +#define SOC_GR9 "GRX200" +#define SOC_VR9 "xRX200" +#define SOC_AR10 "xRX300" +#define SOC_GRX390 "xRX330" #define COMP_DANUBE "lantiq,danube" #define COMP_TWINPASS "lantiq,twinpass" @@ -28,6 +31,8 @@ #define COMP_AR9 "lantiq,ar9" #define COMP_GR9 "lantiq,gr9" #define COMP_VR9 "lantiq,vr9" +#define COMP_AR10 "lantiq,ar10" +#define COMP_GRX390 "lantiq,grx390" #define PART_SHIFT 12 #define PART_MASK 0x0FFFFFFF @@ -108,6 +113,25 @@ void __init ltq_soc_detect(struct ltq_soc_info *i) i->compatible = COMP_GR9; break; + case SOC_ID_ARX362: + case SOC_ID_ARX368: + case SOC_ID_ARX382: + case SOC_ID_ARX388: + case SOC_ID_URX388: + i->name = SOC_AR10; + i->type = SOC_TYPE_AR10; + i->compatible = COMP_AR10; + break; + + case SOC_ID_GRX383: + case SOC_ID_GRX369: + case SOC_ID_GRX387: + case SOC_ID_GRX389: + i->name = SOC_GRX390; + i->type = SOC_TYPE_GRX390; + i->compatible = COMP_GRX390; + break; + default: unreachable(); break; From a3a6853498903dc937710a9f00af8a6679b3e704 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:40 +0100 Subject: [PATCH 081/120] MIPS: Lantiq: Add clock for mei driver Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11391/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index bf9b95c94027..9abb76b5722e 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -495,6 +495,7 @@ void __init ltq_soc_init(void) clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY); clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO); + clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else if (of_machine_is_compatible("lantiq,grx390")) { clkdev_add_static(ltq_grx390_cpu_hz(), ltq_grx390_fpi_hz(), ltq_grx390_fpi_hz(), ltq_grx390_pp32_hz()); @@ -516,6 +517,8 @@ void __init ltq_soc_init(void) PMU_PPE_DP | PMU_PPE_TC); clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); + clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE); + clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else if (of_machine_is_compatible("lantiq,vr9")) { clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz()); @@ -537,6 +540,7 @@ void __init ltq_soc_init(void) PMU_PPE_QSB | PMU_PPE_TOP); clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else if (of_machine_is_compatible("lantiq,ar9")) { clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), ltq_ar9_fpi_hz(), CLOCK_250M); @@ -546,11 +550,13 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P); clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else { clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), ltq_danube_fpi_hz(), ltq_danube_pp32_hz()); clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } } From e71f6d356dccce4ba49a402bf7e9cb44671787cb Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:41 +0100 Subject: [PATCH 082/120] MIPS: Lantiq: Add 1e103100.deu clock Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11392/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 9abb76b5722e..d77bb3ba6219 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -107,6 +107,7 @@ static u32 pmu_clk_cr_b[] = { #define PMU_ASC1 BIT(17) #define PMU_PPE_QSB BIT(18) #define PMU_PPE_SLL01 BIT(19) +#define PMU_DEU BIT(20) #define PMU_PPE_TC BIT(21) #define PMU_PPE_EMA BIT(22) #define PMU_PPE_DPLUM BIT(23) @@ -508,6 +509,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL); clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP); clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); + clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); } else if (of_machine_is_compatible("lantiq,ar10")) { clkdev_add_static(ltq_ar10_cpu_hz(), ltq_ar10_fpi_hz(), ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz()); @@ -517,6 +519,7 @@ void __init ltq_soc_init(void) PMU_PPE_DP | PMU_PPE_TC); clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); + clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else if (of_machine_is_compatible("lantiq,vr9")) { @@ -540,6 +543,7 @@ void __init ltq_soc_init(void) PMU_PPE_QSB | PMU_PPE_TOP); clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else if (of_machine_is_compatible("lantiq,ar9")) { clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), @@ -550,6 +554,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P); clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } else { clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), @@ -557,6 +562,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P); clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); + clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); } } From 5072d8142a830102317411e5599d7347cdd88a9f Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:42 +0100 Subject: [PATCH 083/120] MIPS: Lantiq: Add misc clocks Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11393/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index d77bb3ba6219..60a7eb61c579 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -534,7 +534,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI); clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI); clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL); - clkdev_add_pmu("1d900000.pcie", "ahb", 1, 0, PMU_AHBM | PMU_AHBS); + clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS); clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); clkdev_add_pmu("1e108000.eth", NULL, 1, 0, @@ -556,6 +556,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); + clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0); } else { clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), ltq_danube_fpi_hz(), ltq_danube_pp32_hz()); @@ -564,5 +565,6 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); + clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0); } } From 13648d724549ec5bd986e88ec628c1b42ab0258e Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:43 +0100 Subject: [PATCH 084/120] MIPS: Lantiq: Add support for xRX220 SoC Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11394/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 ++ arch/mips/lantiq/xway/prom.c | 7 +++++++ 2 files changed, 9 insertions(+) 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 3ab4e986d76f..dd6005b75e0c 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -35,6 +35,7 @@ #define SOC_ID_VRX268_2 0x00C /* v1.2 */ #define SOC_ID_GRX288_2 0x00D /* v1.2 */ #define SOC_ID_GRX282_2 0x00E /* v1.2 */ +#define SOC_ID_VRX220 0x000 #define SOC_ID_ARX362 0x004 #define SOC_ID_ARX368 0x005 @@ -55,6 +56,7 @@ #define SOC_TYPE_AMAZON_SE 0x06 #define SOC_TYPE_AR10 0x07 #define SOC_TYPE_GRX390 0x08 +#define SOC_TYPE_VRX220 0x09 /* BOOT_SEL - find what boot media we have */ #define BS_EXT_ROM 0x0 diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c index 2b0386188010..8f6e02f1e965 100644 --- a/arch/mips/lantiq/xway/prom.c +++ b/arch/mips/lantiq/xway/prom.c @@ -22,6 +22,7 @@ #define SOC_AR9 "AR9" #define SOC_GR9 "GRX200" #define SOC_VR9 "xRX200" +#define SOC_VRX220 "xRX220" #define SOC_AR10 "xRX300" #define SOC_GRX390 "xRX330" @@ -106,6 +107,12 @@ void __init ltq_soc_detect(struct ltq_soc_info *i) i->compatible = COMP_VR9; break; + case SOC_ID_VRX220: + i->name = SOC_VRX220; + i->type = SOC_TYPE_VRX220; + i->compatible = COMP_VR9; + break; + case SOC_ID_GRX282_2: case SOC_ID_GRX288_2: i->name = SOC_GR9; From 6e807852676a2ef6f104b56114d7a5096d42ff37 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Oct 2015 23:37:44 +0100 Subject: [PATCH 085/120] MIPS: Lantiq: Fix check for return value of request_mem_region() request_mem_region() returns a pointer and not an integer with an error value. A check for "< 0" on a pointer will cause problems, replace it with not null checks instead. This was found with sparse. Signed-off-by: Hauke Mehrtens Acked-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11395/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/irq.c | 8 ++++---- arch/mips/lantiq/xway/reset.c | 2 +- arch/mips/lantiq/xway/sysctrl.c | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 2c218c3bbca5..2e7f60c9fc5d 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -369,8 +369,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) if (of_address_to_resource(node, i, &res)) panic("Failed to get icu memory range"); - if (request_mem_region(res.start, resource_size(&res), - res.name) < 0) + if (!request_mem_region(res.start, resource_size(&res), + res.name)) pr_err("Failed to request icu memory"); ltq_icu_membase[i] = ioremap_nocache(res.start, @@ -449,8 +449,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) if (ret != exin_avail) panic("failed to load external irq resources"); - if (request_mem_region(res.start, resource_size(&res), - res.name) < 0) + if (!request_mem_region(res.start, resource_size(&res), + res.name)) pr_err("Failed to request eiu memory"); ltq_eiu_membase = ioremap_nocache(res.start, diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 12a7d824d0b6..dd1aaaf8e3e6 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -288,7 +288,7 @@ static int __init mips_reboot_setup(void) if (of_address_to_resource(ltq_rcu_np, 0, &res)) panic("Failed to get rcu memory range"); - if (request_mem_region(res.start, resource_size(&res), res.name) < 0) + if (!request_mem_region(res.start, resource_size(&res), res.name)) pr_err("Failed to request rcu memory"); ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res)); diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 60a7eb61c579..7b3a01456014 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -425,12 +425,12 @@ void __init ltq_soc_init(void) of_address_to_resource(np_ebu, 0, &res_ebu)) panic("Failed to get core resources"); - if ((request_mem_region(res_pmu.start, resource_size(&res_pmu), - res_pmu.name) < 0) || - (request_mem_region(res_cgu.start, resource_size(&res_cgu), - res_cgu.name) < 0) || - (request_mem_region(res_ebu.start, resource_size(&res_ebu), - res_ebu.name) < 0)) + if (!request_mem_region(res_pmu.start, resource_size(&res_pmu), + res_pmu.name) || + !request_mem_region(res_cgu.start, resource_size(&res_cgu), + res_cgu.name) || + !request_mem_region(res_ebu.start, resource_size(&res_ebu), + res_ebu.name)) pr_err("Failed to request core resources"); pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu)); From 39d9b6b223900cdcc36f78c7f9b4173975ca668c Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 21 Oct 2015 11:36:58 +0900 Subject: [PATCH 086/120] MIPS: BMIPS: Add I2C node for bcm7346 Add I2C device nodes to BMIPS based BCM7346 platform. Signed-off-by: Jaedon Shin Acked-by: Florian Fainelli Cc: Wolfram Sang Cc: Kamal Dasu Cc: linux-i2c@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11333/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7346.dtsi | 72 ++++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm97346dbsmb.dts | 20 +++++++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index d817bb46b934..0a1927099075 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -87,14 +87,32 @@ 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 = <59>; + interrupts = <59>, <57>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x408b80 0x8>; + + brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <60>, <58>, <62>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -144,6 +162,56 @@ 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@408980 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x408980 0x58>; + interrupts = <27>; + interrupt-names = "upg_bsce"; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts index 3fe0445b9d37..a5b6365afc5f 100644 --- a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts @@ -29,6 +29,26 @@ status = "okay"; }; +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + +&bsce { + status = "okay"; +}; + &enet0 { status = "okay"; }; From ad8378383e2c705871125f5c9d36936d80068174 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 21 Oct 2015 11:36:59 +0900 Subject: [PATCH 087/120] MIPS: BMIPS: Add I2C node for bcm7358 Add I2C device nodes to BMIPS based BCM7358 platform. Signed-off-by: Jaedon Shin Acked-by: Florian Fainelli Cc: Wolfram Sang Cc: Kamal Dasu Cc: linux-i2c@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11334/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7358.dtsi | 62 +++++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm97358svmb.dts | 16 ++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 277a90adc1a7..8e2501694d03 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -81,14 +81,32 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406600 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 = <56>; + interrupts = <56>, <54>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x408b80 0x8>; + + brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <57>, <55>, <59>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -138,6 +156,46 @@ 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@408980 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x408980 0x58>; + interrupts = <27>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm97358svmb.dts b/arch/mips/boot/dts/brcm/bcm97358svmb.dts index a8dc01e30313..02ce6b429dc4 100644 --- a/arch/mips/boot/dts/brcm/bcm97358svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97358svmb.dts @@ -29,6 +29,22 @@ status = "okay"; }; +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + &enet0 { status = "okay"; }; From fb575b85efd091bad0e0a1220426086c789074d7 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 21 Oct 2015 11:37:00 +0900 Subject: [PATCH 088/120] MIPS: BMIPS: Add I2C node for bcm7360 Add I2C device nodes to BMIPS based BCM7360 platform. Signed-off-by: Jaedon Shin Acked-by: Florian Fainelli Cc: Wolfram Sang Cc: Kamal Dasu Cc: linux-i2c@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11335/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7360.dtsi | 62 +++++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm97360svmb.dts | 16 ++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index 9e1e571ba346..7e5f76040fb8 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -81,14 +81,32 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406600 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 = <56>; + interrupts = <56>, <54>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x408b80 0x8>; + + brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <57>, <55>, <59>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -138,6 +156,46 @@ 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@408980 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x408980 0x58>; + interrupts = <27>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/arch/mips/boot/dts/brcm/bcm97360svmb.dts index eee8b0e32681..d48462e091f1 100644 --- a/arch/mips/boot/dts/brcm/bcm97360svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97360svmb.dts @@ -29,6 +29,22 @@ status = "okay"; }; +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscc { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + &enet0 { status = "okay"; }; From f50cbf5329e045e8d69046ea9093e6bafdc09516 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Wed, 21 Oct 2015 11:37:01 +0900 Subject: [PATCH 089/120] MIPS: BMIPS: Add I2C node for bcm7362 Add I2C device nodes to BMIPS based BCM7362 platform. Signed-off-by: Jaedon Shin Acked-by: Florian Fainelli Cc: Wolfram Sang Cc: Kamal Dasu Cc: linux-i2c@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11336/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7362.dtsi | 52 +++++++++++++++++++++++- arch/mips/boot/dts/brcm/bcm97362svmb.dts | 12 ++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index 6e65db86fc61..5f817be2553c 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -87,14 +87,32 @@ compatible = "brcm,bcm7120-l2-intc"; reg = <0x406600 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 = <56>; + interrupts = <56>, <54>; + interrupt-names = "upg_main", "upg_bsc"; + }; + + upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x408b80 0x8>; + + brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>; + brcm,int-fwd-mask = <0>; + brcm,irq-can-wake; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <57>, <55>, <59>; + interrupt-names = "upg_main_aon", "upg_bsc_aon", + "upg_spi"; }; sun_top_ctrl: syscon@404000 { @@ -144,6 +162,36 @@ 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"; + }; + + bscd: i2c@408980 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&upg_aon_irq0_intc>; + reg = <0x408980 0x58>; + interrupts = <27>; + interrupt-names = "upg_bscd"; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm97362svmb.dts b/arch/mips/boot/dts/brcm/bcm97362svmb.dts index 739c2ef5663b..9c99bfd1e781 100644 --- a/arch/mips/boot/dts/brcm/bcm97362svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97362svmb.dts @@ -29,6 +29,18 @@ status = "okay"; }; +&bsca { + status = "okay"; +}; + +&bscb { + status = "okay"; +}; + +&bscd { + status = "okay"; +}; + &enet0 { status = "okay"; }; From ce6df6376a1eeb63c694f8e82e9563b59c5506a6 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Tue, 27 Oct 2015 15:48:09 +0900 Subject: [PATCH 090/120] MIPS: BMIPS: Add SATA/PHY nodes for bcm7425 Add AHCI and PHY device nodes to MIPS-based BCM7425 set-top box platform. Signed-off-by: Jaedon Shin Cc: Brian Norris Cc: Florian Fainelli Cc: Tejun Heo Cc: Kishon Vijay Abraham I Cc: Rob Herring Cc: Kevin Cernekee Cc: Dragan Stancevic Cc: linux-ide@vger.kernel.org Cc: Linux-MIPS Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11377/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7425.dtsi | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 5b660b617ead..e24d41ab4e30 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -221,5 +221,47 @@ interrupts = <73>; 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 = <40>; + #address-cells = <1>; + #size-cells = <0>; + brcm,broken-ncq; + brcm,broken-phy; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + }; + }; + + sata_phy: sata-phy@1800000 { + 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>; + }; + }; }; }; From 19e88101c78fdbfb93580f7ac0eb64eea040cbb6 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Tue, 27 Oct 2015 15:48:10 +0900 Subject: [PATCH 091/120] MIPS: BMIPS: Add SATA/PHY nodes for bcm7346 Add AHCI and PHY device nodes to MIPS-based BCM7346 set-top box platform. Signed-off-by: Jaedon Shin Cc: Brian Norris Cc: Florian Fainelli Cc: Tejun Heo Cc: Kishon Vijay Abraham I Cc: Rob Herring Cc: Kevin Cernekee Cc: Dragan Stancevic Cc: linux-ide@vger.kernel.org Cc: Linux-MIPS Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11378/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7346.dtsi | 42 +++++++++++++++++++++++ arch/mips/boot/dts/brcm/bcm97346dbsmb.dts | 8 +++++ 2 files changed, 50 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index 0a1927099075..d4bf52cfcf17 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -314,5 +314,47 @@ interrupts = <76>; 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 = <40>; + #address-cells = <1>; + #size-cells = <0>; + brcm,broken-ncq; + brcm,broken-phy; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + }; + }; + + sata_phy: sata-phy@1800000 { + 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/bcm97346dbsmb.dts b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts index a5b6365afc5f..d3d28816a027 100644 --- a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts @@ -84,3 +84,11 @@ &ohci3 { status = "okay"; }; + +&sata { + status = "okay"; +}; + +&sata_phy { + status = "okay"; +}; From 1b04be20f6e38672d81f2de844488164bca988ca Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Tue, 27 Oct 2015 15:48:11 +0900 Subject: [PATCH 092/120] MIPS: BMIPS: Add SATA/PHY nodes for bcm7362 Add AHCI and PHY device nodes to MIPS-based BCM7362 set-top box platform. Signed-off-by: Jaedon Shin Cc: Brian Norris Cc: Florian Fainelli Cc: Tejun Heo Cc: Kishon Vijay Abraham I Cc: Rob Herring Cc: Kevin Cernekee Cc: Dragan Stancevic Cc: linux-ide@vger.kernel.org Cc: Linux-MIPS Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11379/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm7362.dtsi | 42 ++++++++++++++++++++++++ arch/mips/boot/dts/brcm/bcm97362svmb.dts | 8 +++++ 2 files changed, 50 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index 5f817be2553c..c739ea77acb0 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -237,5 +237,47 @@ 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>; + brcm,broken-ncq; + brcm,broken-phy; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <&sata_phy0>; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <&sata_phy1>; + }; + }; + + sata_phy: sata-phy@1800000 { + 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/bcm97362svmb.dts b/arch/mips/boot/dts/brcm/bcm97362svmb.dts index 9c99bfd1e781..3cfcaebe7f79 100644 --- a/arch/mips/boot/dts/brcm/bcm97362svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97362svmb.dts @@ -52,3 +52,11 @@ &ohci0 { status = "okay"; }; + +&sata { + status = "okay"; +}; + +&sata_phy { + status = "okay"; +}; From 81857db913e9782546d29b52cd3efc80c0145c23 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:06 +0100 Subject: [PATCH 093/120] MIPS: ralink: Add support for mt7688 MT7688 is similar tot he MT7628 but has a different wifi radio. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11439/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ralink/mt7620.h | 1 + arch/mips/ralink/mt7620.c | 35 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 1976fb815fd1..590681af4bed 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -24,6 +24,7 @@ enum mt762x_soc_type { #define SYSC_REG_CHIP_NAME0 0x00 #define SYSC_REG_CHIP_NAME1 0x04 +#define SYSC_REG_EFUSE_CFG 0x08 #define SYSC_REG_CHIP_REV 0x0c #define SYSC_REG_SYSTEM_CONFIG0 0x10 #define SYSC_REG_SYSTEM_CONFIG1 0x14 diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 2ea5ff6dc22e..4d1a0339dd54 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -40,6 +40,12 @@ /* is this a MT7620 or a MT7628 */ enum mt762x_soc_type mt762x_soc; +/* EFUSE bits */ +#define EFUSE_MT7688 0x100000 + +/* DRAM type bit */ +#define DRAM_TYPE_MT7628_MASK 0x1 + /* does the board have sdram or ddram */ static int dram_type; @@ -227,6 +233,12 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = { { 0 } }; +static inline int is_mt76x8(void) +{ + return mt762x_soc == MT762X_SOC_MT7628AN || + mt762x_soc == MT762X_SOC_MT7688; +} + static __init u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) { @@ -381,7 +393,7 @@ void __init ralink_clk_init(void) #define RINT(x) ((x) / 1000000) #define RFRAC(x) (((x) / 1000) % 1000) - if (mt762x_soc == MT762X_SOC_MT7628AN) { + if (is_mt76x8()) { if (xtal_rate == MHZ(40)) cpu_rate = MHZ(580); else @@ -511,8 +523,15 @@ void prom_soc_init(struct ralink_soc_info *soc_info) #endif } } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { - mt762x_soc = MT762X_SOC_MT7628AN; - name = "MT7628AN"; + u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG); + + if (efuse & EFUSE_MT7688) { + mt762x_soc = MT762X_SOC_MT7688; + name = "MT7688"; + } else { + mt762x_soc = MT762X_SOC_MT7628AN; + name = "MT7628AN"; + } soc_info->compatible = "ralink,mt7628an-soc"; } else { panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1); @@ -525,10 +544,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info) (rev & CHIP_REV_ECO_MASK)); cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); - dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + if (is_mt76x8()) + dram_type = cfg0 & DRAM_TYPE_MT7628_MASK; + else + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & + SYSCFG0_DRAM_TYPE_MASK; soc_info->mem_base = MT7620_DRAM_BASE; - if (mt762x_soc == MT762X_SOC_MT7628AN) + if (is_mt76x8()) mt7628_dram_init(soc_info); else mt7620_dram_init(soc_info); @@ -541,7 +564,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info) pr_info("Digital PMU set to %s control\n", (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); - if (mt762x_soc == MT762X_SOC_MT7628AN) + if (is_mt76x8()) rt2880_pinmux_data = mt7628an_pinmux_data; else rt2880_pinmux_data = mt7620a_pinmux_data; From 418d29c8706170c6801998e48341181b274a47a8 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:07 +0100 Subject: [PATCH 094/120] MIPS: ralink: Unify SoC id handling This makes detection a lot easier for audio, wifi, ... drivers. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11440/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ralink/mt7620.h | 7 ------- .../include/asm/mach-ralink/ralink_regs.h | 17 +++++++++++++++ arch/mips/include/asm/mach-ralink/rt305x.h | 21 ++++++------------- arch/mips/ralink/mt7620.c | 15 ++++++------- arch/mips/ralink/prom.c | 5 +++++ arch/mips/ralink/rt288x.c | 1 + arch/mips/ralink/rt305x.c | 12 +++++------ arch/mips/ralink/rt3883.c | 2 ++ 8 files changed, 42 insertions(+), 38 deletions(-) diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 590681af4bed..455d406e8ddf 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -13,13 +13,6 @@ #ifndef _MT7620_REGS_H_ #define _MT7620_REGS_H_ -enum mt762x_soc_type { - MT762X_SOC_UNKNOWN = 0, - MT762X_SOC_MT7620A, - MT762X_SOC_MT7620N, - MT762X_SOC_MT7628AN, -}; - #define MT7620_SYSC_BASE 0x10000000 #define SYSC_REG_CHIP_NAME0 0x00 diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h index bd93014490df..4c9fba68c8b2 100644 --- a/arch/mips/include/asm/mach-ralink/ralink_regs.h +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h @@ -13,6 +13,23 @@ #ifndef _RALINK_REGS_H_ #define _RALINK_REGS_H_ +enum ralink_soc_type { + RALINK_UNKNOWN = 0, + RT2880_SOC, + RT3883_SOC, + RT305X_SOC_RT3050, + RT305X_SOC_RT3052, + RT305X_SOC_RT3350, + RT305X_SOC_RT3352, + RT305X_SOC_RT5350, + MT762X_SOC_MT7620A, + MT762X_SOC_MT7620N, + MT762X_SOC_MT7621AT, + MT762X_SOC_MT7628AN, + MT762X_SOC_MT7688, +}; +extern enum ralink_soc_type ralink_soc; + extern __iomem void *rt_sysc_membase; extern __iomem void *rt_memc_membase; diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index 96f731bac79a..2eea79331a14 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -13,25 +13,16 @@ #ifndef _RT305X_REGS_H_ #define _RT305X_REGS_H_ -enum rt305x_soc_type { - RT305X_SOC_UNKNOWN = 0, - RT305X_SOC_RT3050, - RT305X_SOC_RT3052, - RT305X_SOC_RT3350, - RT305X_SOC_RT3352, - RT305X_SOC_RT5350, -}; - -extern enum rt305x_soc_type rt305x_soc; +extern enum ralink_soc_type ralink_soc; static inline int soc_is_rt3050(void) { - return rt305x_soc == RT305X_SOC_RT3050; + return ralink_soc == RT305X_SOC_RT3050; } static inline int soc_is_rt3052(void) { - return rt305x_soc == RT305X_SOC_RT3052; + return ralink_soc == RT305X_SOC_RT3052; } static inline int soc_is_rt305x(void) @@ -41,17 +32,17 @@ static inline int soc_is_rt305x(void) static inline int soc_is_rt3350(void) { - return rt305x_soc == RT305X_SOC_RT3350; + return ralink_soc == RT305X_SOC_RT3350; } static inline int soc_is_rt3352(void) { - return rt305x_soc == RT305X_SOC_RT3352; + return ralink_soc == RT305X_SOC_RT3352; } static inline int soc_is_rt5350(void) { - return rt305x_soc == RT305X_SOC_RT5350; + return ralink_soc == RT305X_SOC_RT5350; } #define RT305X_SYSC_BASE 0x10000000 diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 4d1a0339dd54..f3a4a08f2e71 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -37,9 +37,6 @@ #define PMU1_CFG 0x8C #define DIG_SW_SEL BIT(25) -/* is this a MT7620 or a MT7628 */ -enum mt762x_soc_type mt762x_soc; - /* EFUSE bits */ #define EFUSE_MT7688 0x100000 @@ -235,8 +232,8 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = { static inline int is_mt76x8(void) { - return mt762x_soc == MT762X_SOC_MT7628AN || - mt762x_soc == MT762X_SOC_MT7688; + return ralink_soc == MT762X_SOC_MT7628AN || + ralink_soc == MT762X_SOC_MT7688; } static __init u32 @@ -511,11 +508,11 @@ void prom_soc_init(struct ralink_soc_info *soc_info) if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) { if (bga) { - mt762x_soc = MT762X_SOC_MT7620A; + ralink_soc = MT762X_SOC_MT7620A; name = "MT7620A"; soc_info->compatible = "ralink,mt7620a-soc"; } else { - mt762x_soc = MT762X_SOC_MT7620N; + ralink_soc = MT762X_SOC_MT7620N; name = "MT7620N"; soc_info->compatible = "ralink,mt7620n-soc"; #ifdef CONFIG_PCI @@ -526,10 +523,10 @@ void prom_soc_init(struct ralink_soc_info *soc_info) u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG); if (efuse & EFUSE_MT7688) { - mt762x_soc = MT762X_SOC_MT7688; + ralink_soc = MT762X_SOC_MT7688; name = "MT7688"; } else { - mt762x_soc = MT762X_SOC_MT7628AN; + ralink_soc = MT762X_SOC_MT7628AN; name = "MT7628AN"; } soc_info->compatible = "ralink,mt7628an-soc"; diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c index 09419f67da39..39a9142f71be 100644 --- a/arch/mips/ralink/prom.c +++ b/arch/mips/ralink/prom.c @@ -15,11 +15,16 @@ #include #include +#include + #include "common.h" struct ralink_soc_info soc_info; struct rt2880_pmx_group *rt2880_pinmux_data = NULL; +enum ralink_soc_type ralink_soc; +EXPORT_SYMBOL_GPL(ralink_soc); + const char *get_system_type(void) { return soc_info.sys_type; diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index 738cec865f41..844f5cd55c8f 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c @@ -119,4 +119,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; rt2880_pinmux_data = rt2880_pinmux_data_act; + ralink_soc == RT2880_SOC; } diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index c40776ab67db..7e11f001e8ff 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -21,8 +21,6 @@ #include "common.h" -enum rt305x_soc_type rt305x_soc; - static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; static struct rt2880_pmx_func uartf_func[] = { @@ -235,24 +233,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info) icache_sets = (read_c0_config1() >> 22) & 7; if (icache_sets == 1) { - rt305x_soc = RT305X_SOC_RT3050; + ralink_soc = RT305X_SOC_RT3050; name = "RT3050"; soc_info->compatible = "ralink,rt3050-soc"; } else { - rt305x_soc = RT305X_SOC_RT3052; + ralink_soc = RT305X_SOC_RT3052; name = "RT3052"; soc_info->compatible = "ralink,rt3052-soc"; } } else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) { - rt305x_soc = RT305X_SOC_RT3350; + ralink_soc = RT305X_SOC_RT3350; name = "RT3350"; soc_info->compatible = "ralink,rt3350-soc"; } else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) { - rt305x_soc = RT305X_SOC_RT3352; + ralink_soc = RT305X_SOC_RT3352; name = "RT3352"; soc_info->compatible = "ralink,rt3352-soc"; } else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) { - rt305x_soc = RT305X_SOC_RT5350; + ralink_soc = RT305X_SOC_RT5350; name = "RT5350"; soc_info->compatible = "ralink,rt5350-soc"; } else { diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index 86a535c770d8..582995aaaf4e 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -153,4 +153,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info) soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; rt2880_pinmux_data = rt3883_pinmux_data; + + ralink_soc == RT3883_SOC; } From b361bd762e7724e660a44955ae4840aa984e3871 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:08 +0100 Subject: [PATCH 095/120] MIPS: ralink: Fix usb issue during frequency scaling If the USB HCD is running and the cpu is scaled too low, then the USB stops working. Increase the idle speed of the core to fix this if the kernel is built with USB support. The "magic" values are taken from the Ralink SDK Kernel. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11441/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/mt7620.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index f3a4a08f2e71..55ddf09d8676 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -37,6 +37,12 @@ #define PMU1_CFG 0x8C #define DIG_SW_SEL BIT(25) +/* clock scaling */ +#define CLKCFG_FDIV_MASK 0x1f00 +#define CLKCFG_FDIV_USB_VAL 0x0300 +#define CLKCFG_FFRAC_MASK 0x001f +#define CLKCFG_FFRAC_USB_VAL 0x0003 + /* EFUSE bits */ #define EFUSE_MT7688 0x100000 @@ -432,6 +438,20 @@ void __init ralink_clk_init(void) ralink_clk_add("10000b00.spi", sys_rate); ralink_clk_add("10000c00.uartlite", periph_rate); ralink_clk_add("10180000.wmac", xtal_rate); + + if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) { + /* + * When the CPU goes into sleep mode, the BUS clock will be + * too low for USB to function properly. Adjust the busses + * fractional divider to fix this + */ + u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); + + val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); + val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; + + rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG); + } } void __init ralink_of_remap(void) From 73afa6c4208257ea1733a03918fea731a18131e7 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 5 Nov 2015 03:59:58 +0100 Subject: [PATCH 096/120] MIPS: ralink: Add tty detection MT7688 has several uarts that can be used for console. There are several boards in the wild, that use ttyS1 or ttyS2. This patch applies a simply autodetection routine to figure out which ttyS the bootloader used as console. The uarts come up in 6 bit mode by default. The bootloader will have set 8 bit mode on the console. Find that 8bit tty and use it. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11459/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/early_printk.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c index 255d695ec8c6..3c59ffe5f5f5 100644 --- a/arch/mips/ralink/early_printk.c +++ b/arch/mips/ralink/early_printk.c @@ -25,11 +25,13 @@ #define MT7628_CHIP_NAME1 0x20203832 #define UART_REG_TX 0x04 +#define UART_REG_LCR 0x0c #define UART_REG_LSR 0x14 #define UART_REG_LSR_RT2880 0x1c static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE); +static int init_complete; static inline void uart_w32(u32 val, unsigned reg) { @@ -47,8 +49,32 @@ static inline int soc_is_mt7628(void) (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1); } +static void find_uart_base(void) +{ + int i; + + if (!soc_is_mt7628()) + return; + + for (i = 0; i < 3; i++) { + u32 reg = uart_r32(UART_REG_LCR + (0x100 * i)); + + if (!reg) + continue; + + uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE + + (0x100 * i)); + break; + } +} + void prom_putchar(unsigned char ch) { + if (!init_complete) { + find_uart_base(); + init_complete = 1; + } + if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) { uart_w32(ch, UART_TX); while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) From 37bcc03f97e05cc65ce87d3b2fdcd4e5b28ce06c Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:10 +0100 Subject: [PATCH 097/120] MIPS: ralink: Fix invalid tick count The current code adds the delta twice, which is obviously wrong. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11443/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/cevt-rt3352.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index a8e70a9f274b..e46f91f971c5 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -48,7 +48,7 @@ static int systick_next_event(unsigned long delta, sdev = container_of(evt, struct systick_device, dev); count = ioread32(sdev->membase + SYSTICK_COUNT); count = (count + delta) % SYSTICK_FREQ; - iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE); + iowrite32(count, sdev->membase + SYSTICK_COMPARE); return 0; } From bc19f5d677c10f323650e6bb5fe45ab5fb11e9a9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:11 +0100 Subject: [PATCH 098/120] MIPS: ralink: Remove check for CONFIG_PCI on non-PCI SoCs The code currently panics if PCI is enabled but the SoC has no PCI bus. This check is superfluous as the driver only loads if enabled in the devicetree. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11444/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/mt7620.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 55ddf09d8676..dfb04fcedb04 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -535,9 +535,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info) ralink_soc = MT762X_SOC_MT7620N; name = "MT7620N"; soc_info->compatible = "ralink,mt7620n-soc"; -#ifdef CONFIG_PCI - panic("mt7620n is only supported for non pci kernels"); -#endif } } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG); From 81ab9f6c5ff8565e4cba330e340a8979a10521d7 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:12 +0100 Subject: [PATCH 099/120] MIPS: ralink: Don't set pm_power_off Setting pm_power_off is apprently wrong and makes drivers such as gpio-poweroff not work. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11445/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/reset.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index 55c7ec59df3c..ee26d45e48e7 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -98,7 +98,6 @@ static int __init mips_reboot_setup(void) { _machine_restart = ralink_restart; _machine_halt = ralink_halt; - pm_power_off = ralink_halt; return 0; } From 1a93520504aa035f037e7e255aee670561a38946 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:13 +0100 Subject: [PATCH 100/120] MIPS: ralink: Put the pci bus into reset state before rebooting the SoC Some pcie cards have problems after a reboot without this. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11446/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/reset.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index ee26d45e48e7..ee117c4bc4a3 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -18,8 +19,10 @@ #include /* Reset Control */ -#define SYSC_REG_RESET_CTRL 0x034 -#define RSTCTL_RESET_SYSTEM BIT(0) +#define SYSC_REG_RESET_CTRL 0x034 + +#define RSTCTL_RESET_PCI BIT(26) +#define RSTCTL_RESET_SYSTEM BIT(0) static int ralink_assert_device(struct reset_controller_dev *rcdev, unsigned long id) @@ -83,6 +86,11 @@ void ralink_rst_init(void) static void ralink_restart(char *command) { + if (IS_ENABLED(CONFIG_PCI)) { + rt_sysc_m32(0, RSTCTL_RESET_PCI, SYSC_REG_RESET_CTRL); + mdelay(50); + } + local_irq_disable(); rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL); unreachable(); From 69ebed7dc9311ea383dd0b9542c823a51b20e679 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 11:50:14 +0100 Subject: [PATCH 101/120] MIPS: ralink: Add missing clock on rt305x The rt305x support is missing a clock required by the ethernet driver. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11447/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/rt305x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index 7e11f001e8ff..9e4572592065 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -199,6 +199,7 @@ void __init ralink_clk_init(void) } ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("sys", sys_rate); ralink_clk_add("10000b00.spi", sys_rate); ralink_clk_add("10000100.timer", wdt_rate); ralink_clk_add("10000120.watchdog", wdt_rate); From 1601078df26605da7a8107bdd3143ef6b9d07e3b Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 13:14:13 +0100 Subject: [PATCH 102/120] MIPS: lantiq: Return correct value for fpi clock on ar9 Some configurations of AR9 reported the incorrect speed for the fpi bus. Signed-off-by: Ben Mulvihill Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11448/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/clk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 80aad3080ef8..07f6d5b0b65e 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -88,8 +88,9 @@ unsigned long ltq_ar9_fpi_hz(void) unsigned long sys = ltq_ar9_sys_hz(); if (ltq_cgu_r32(CGU_SYS) & BIT(0)) - return sys; - return sys >> 1; + return sys / 3; + else + return sys / 2; } unsigned long ltq_ar9_cpu_hz(void) From 26cfdbe30d81c209a5e81c4c311b02b10b5821c3 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 13:14:14 +0100 Subject: [PATCH 103/120] MIPS: lantiq: Initialize the USB core on boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a DWC2 USB core in these SoCs. To make USB work we need to first reset and power the state machine. These are SoC specific registers and not part of the actual USB core. Signed-off-by: Antti Seppälä Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11449/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/reset.c | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index dd1aaaf8e3e6..4b52ce6d38f8 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -60,6 +60,37 @@ #define RCU_BOOT_SEL(x) ((x >> 18) & 0x7) #define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10)) +/* dwc2 USB configuration registers */ +#define RCU_USB1CFG 0x0018 +#define RCU_USB2CFG 0x0034 + +/* USB DMA endianness bits */ +#define RCU_USBCFG_HDSEL_BIT BIT(11) +#define RCU_USBCFG_HOST_END_BIT BIT(10) +#define RCU_USBCFG_SLV_END_BIT BIT(9) + +/* USB reset bits */ +#define RCU_USBRESET 0x0010 + +#define USBRESET_BIT BIT(4) + +#define RCU_USBRESET2 0x0048 + +#define USB1RESET_BIT BIT(4) +#define USB2RESET_BIT BIT(5) + +#define RCU_CFG1A 0x0038 +#define RCU_CFG1B 0x003C + +/* USB PMU devices */ +#define PMU_AHBM BIT(15) +#define PMU_USB0 BIT(6) +#define PMU_USB1 BIT(27) + +/* USB PHY PMU devices */ +#define PMU_USB0_P BIT(0) +#define PMU_USB1_P BIT(26) + /* remapped base addr of the reset control unit */ static void __iomem *ltq_rcu_membase; static struct device_node *ltq_rcu_np; @@ -272,6 +303,45 @@ static void ltq_machine_power_off(void) unreachable(); } +static void ltq_usb_init(void) +{ + /* Power for USB cores 1 & 2 */ + ltq_pmu_enable(PMU_AHBM); + ltq_pmu_enable(PMU_USB0); + ltq_pmu_enable(PMU_USB1); + + ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A); + ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B); + + /* Enable USB PHY power for cores 1 & 2 */ + ltq_pmu_enable(PMU_USB0_P); + ltq_pmu_enable(PMU_USB1_P); + + /* Configure cores to host mode */ + ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT, + RCU_USB1CFG); + ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT, + RCU_USB2CFG); + + /* Select DMA endianness (Host-endian: big-endian) */ + ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT) + | RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG); + ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT) + | RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG); + + /* Hard reset USB state machines */ + ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET); + udelay(50 * 1000); + ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET); + + /* Soft reset USB state machines */ + ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) + | USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2); + udelay(50 * 1000); + ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) + & ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2); +} + static int __init mips_reboot_setup(void) { struct resource res; @@ -295,6 +365,10 @@ static int __init mips_reboot_setup(void) if (!ltq_rcu_membase) panic("Failed to remap core memory"); + if (of_machine_is_compatible("lantiq,ar9") || + of_machine_is_compatible("lantiq,vr9")) + ltq_usb_init(); + _machine_restart = ltq_machine_restart; _machine_halt = ltq_machine_halt; pm_power_off = ltq_machine_power_off; From 9eb8c69e0b00d5e7970a682454180780b6a3d020 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 4 Nov 2015 13:14:15 +0100 Subject: [PATCH 104/120] MIPS: lantiq: Force the crossbar to big endian Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11450/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/reset.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 4b52ce6d38f8..bc29bb349e94 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -40,6 +40,10 @@ #define RCU_GFS_ADD2_XRX330 0x00AC #define RCU_GFS_ADD3_XRX330 0x0264 +/* xbar BE flag */ +#define RCU_AHB_ENDIAN 0x004C +#define RCU_VR9_BE_AHB1S 0x00000008 + /* reboot bit */ #define RCU_RD_GPHY0_XRX200 BIT(31) #define RCU_RD_SRST BIT(30) @@ -369,6 +373,10 @@ static int __init mips_reboot_setup(void) of_machine_is_compatible("lantiq,vr9")) ltq_usb_init(); + if (of_machine_is_compatible("lantiq,vr9")) + ltq_rcu_w32(ltq_rcu_r32(RCU_AHB_ENDIAN) | RCU_VR9_BE_AHB1S, + RCU_AHB_ENDIAN); + _machine_restart = ltq_machine_restart; _machine_halt = ltq_machine_halt; pm_power_off = ltq_machine_power_off; From 08b3c894e56580b8ed3e601212a25bda974c3cc2 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 5 Nov 2015 03:56:23 +0100 Subject: [PATCH 105/120] MIPS: lantiq: Disable xbar fpi burst mode Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11458/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 7b3a01456014..80554e8f6037 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -145,7 +145,15 @@ static u32 pmu_clk_cr_b[] = { #define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y)) #define pmu_r32(x) ltq_r32(pmu_membase + (x)) +#define XBAR_ALWAYS_LAST 0x430 +#define XBAR_FPI_BURST_EN BIT(1) +#define XBAR_AHB_BURST_EN BIT(2) + +#define xbar_w32(x, y) ltq_w32((x), ltq_xbar_membase + (y)) +#define xbar_r32(x) ltq_r32(ltq_xbar_membase + (x)) + static void __iomem *pmu_membase; +static void __iomem *ltq_xbar_membase; void __iomem *ltq_cgu_membase; void __iomem *ltq_ebu_membase; @@ -285,6 +293,16 @@ static void pci_ext_disable(struct clk *clk) ltq_cgu_w32((1 << 31) | (1 << 30), pcicr); } +static void xbar_fpi_burst_disable(void) +{ + u32 reg; + + /* bit 1 as 1 --burst; bit 1 as 0 -- single */ + reg = xbar_r32(XBAR_ALWAYS_LAST); + reg &= ~XBAR_FPI_BURST_EN; + xbar_w32(reg, XBAR_ALWAYS_LAST); +} + /* enable a clockout source */ static int clkout_enable(struct clk *clk) { @@ -441,6 +459,26 @@ void __init ltq_soc_init(void) if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase) panic("Failed to remap core resources"); + if (of_machine_is_compatible("lantiq,vr9")) { + struct resource res_xbar; + struct device_node *np_xbar = + of_find_compatible_node(NULL, NULL, + "lantiq,xbar-xway"); + + if (!np_xbar) + panic("Failed to load xbar nodes from devicetree"); + if (of_address_to_resource(np_pmu, 0, &res_xbar)) + panic("Failed to get xbar resources"); + if (request_mem_region(res_xbar.start, resource_size(&res_xbar), + res_xbar.name) < 0) + panic("Failed to get xbar resources"); + + ltq_xbar_membase = ioremap_nocache(res_xbar.start, + resource_size(&res_xbar)); + if (!ltq_xbar_membase) + panic("Failed to remap xbar resources"); + } + /* make sure to unprotect the memory region where flash is located */ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); @@ -567,4 +605,7 @@ void __init ltq_soc_init(void) clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0); } + + if (of_machine_is_compatible("lantiq,vr9")) + xbar_fpi_burst_disable(); } From 5361832704d3224c09dd5732ae656d9d5014c1d8 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 7 Oct 2015 14:07:59 +0800 Subject: [PATCH 106/120] MIPS: Loongson: Cleanup CONFIG_LOONGSON_SUSPEND. Now LOONGSON_CHIPCFG register definition doesn't depend on CPUFREQ any more, so CPU_SUPPORTS_CPUFREQ is no longer needed for suspend/resume. Remove CONFIG_LOONGSON_SUSPEND and use CONFIG_SUSPEND instead. 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/11274/ Signed-off-by: Ralf Baechle --- arch/mips/loongson64/Kconfig | 5 ----- arch/mips/loongson64/common/Makefile | 2 +- arch/mips/loongson64/lemote-2f/Makefile | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/mips/loongson64/Kconfig b/arch/mips/loongson64/Kconfig index 497912b38d8e..8e6e292675b2 100644 --- a/arch/mips/loongson64/Kconfig +++ b/arch/mips/loongson64/Kconfig @@ -120,11 +120,6 @@ config RS780_HPET If unsure, say Yes. -config LOONGSON_SUSPEND - bool - default y - depends on CPU_SUPPORTS_CPUFREQ && SUSPEND - config LOONGSON_UART_BASE bool default y diff --git a/arch/mips/loongson64/common/Makefile b/arch/mips/loongson64/common/Makefile index f2e8153e44f5..074d9cb15cd2 100644 --- a/arch/mips/loongson64/common/Makefile +++ b/arch/mips/loongson64/common/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_CS5536) += cs5536/ # Suspend Support # -obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += pm.o # # Big Memory (SWIOTLB) Support diff --git a/arch/mips/loongson64/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile index 4f9eaa328a16..08b8abcbfef5 100644 --- a/arch/mips/loongson64/lemote-2f/Makefile +++ b/arch/mips/loongson64/lemote-2f/Makefile @@ -8,4 +8,4 @@ obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o # Suspend Support # -obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += pm.o From 63893ea5304c919656613a47b04e35c6814d9041 Mon Sep 17 00:00:00 2001 From: Gregory Fong Date: Wed, 14 Oct 2015 04:27:38 -0700 Subject: [PATCH 107/120] MIPS: BCM63XX: Use pr_* instead of printk Signed-off-by: Gregory Fong Cc: Florian Fainelli Cc: Jonas Gorski Cc: Joe Perches Cc: Rusty Russell Cc: Nicolas Schichan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11300/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/boards/board_bcm963xx.c | 14 +++++++------- arch/mips/bcm63xx/cpu.c | 12 ++++++------ arch/mips/bcm63xx/dev-pcmcia.c | 2 +- arch/mips/bcm63xx/irq.c | 2 +- arch/mips/bcm63xx/setup.c | 8 ++++---- arch/mips/bcm63xx/timer.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 33727e7f0c79..b2097c0d2ed7 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -7,6 +7,8 @@ * Copyright (C) 2008 Florian Fainelli */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -31,7 +33,6 @@ #include -#define PFX "board_bcm963xx: " #define HCS_OFFSET_128K 0x20000 @@ -740,7 +741,7 @@ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom)); return 0; } else { - printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n"); + pr_err("unable to fill SPROM for given bustype\n"); return -EINVAL; } } @@ -784,7 +785,7 @@ void __init board_prom_init(void) cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]); else strcpy(cfe_version, "unknown"); - printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); + pr_info("CFE version: %s\n", cfe_version); bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET); @@ -808,8 +809,7 @@ void __init board_prom_init(void) char name[17]; memcpy(name, board_name, 16); name[16] = 0; - printk(KERN_ERR PFX "unknown bcm963xx board: %s\n", - name); + pr_err("unknown bcm963xx board: %s\n", name); return; } @@ -854,7 +854,7 @@ void __init board_setup(void) { if (!board.name[0]) panic("unable to detect bcm963xx board"); - printk(KERN_INFO PFX "board name: %s\n", board.name); + pr_info("board name: %s\n", board.name); /* make sure we're running on expected cpu */ if (bcm63xx_get_cpu_id() != board.expected_cpu_id) @@ -910,7 +910,7 @@ int __init board_register_devices(void) memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); if (ssb_arch_register_fallback_sprom( &bcm63xx_get_fallback_sprom) < 0) - pr_err(PFX "failed to register fallback SPROM\n"); + pr_err("failed to register fallback SPROM\n"); } #endif diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 307ec8b8e41c..1c7c3fbfa1f3 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -376,10 +376,10 @@ void __init bcm63xx_cpu_init(void) bcm63xx_cpu_freq = detect_cpu_clock(); bcm63xx_memory_size = detect_memory_size(); - printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x\n", - bcm63xx_cpu_id, bcm63xx_cpu_rev); - printk(KERN_INFO "CPU frequency is %u MHz\n", - bcm63xx_cpu_freq / 1000000); - printk(KERN_INFO "%uMB of RAM installed\n", - bcm63xx_memory_size >> 20); + pr_info("Detected Broadcom 0x%04x CPU revision %02x\n", + bcm63xx_cpu_id, bcm63xx_cpu_rev); + pr_info("CPU frequency is %u MHz\n", + bcm63xx_cpu_freq / 1000000); + pr_info("%uMB of RAM installed\n", + bcm63xx_memory_size >> 20); } diff --git a/arch/mips/bcm63xx/dev-pcmcia.c b/arch/mips/bcm63xx/dev-pcmcia.c index a551bab5ecb9..9496cd236951 100644 --- a/arch/mips/bcm63xx/dev-pcmcia.c +++ b/arch/mips/bcm63xx/dev-pcmcia.c @@ -139,6 +139,6 @@ int __init bcm63xx_pcmcia_register(void) return platform_device_register(&bcm63xx_pcmcia_device); out_err: - printk(KERN_ERR "unable to set pcmcia chip select\n"); + pr_err("unable to set pcmcia chip select\n"); return ret; } diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 1a47ec2a0906..c96139097ae2 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -311,7 +311,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, break; default: - printk(KERN_ERR "bogus flow type combination given !\n"); + pr_err("bogus flow type combination given !\n"); return -EINVAL; } diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 240fb4ffa55c..2be9caaa2085 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -24,7 +24,7 @@ void bcm63xx_machine_halt(void) { - printk(KERN_INFO "System halted\n"); + pr_info("System halted\n"); while (1) ; } @@ -34,7 +34,7 @@ static void bcm6348_a1_reboot(void) u32 reg; /* soft reset all blocks */ - printk(KERN_INFO "soft-resetting all blocks ...\n"); + pr_info("soft-resetting all blocks ...\n"); reg = bcm_perf_readl(PERF_SOFTRESET_REG); reg &= ~SOFTRESET_6348_ALL; bcm_perf_writel(reg, PERF_SOFTRESET_REG); @@ -46,7 +46,7 @@ static void bcm6348_a1_reboot(void) mdelay(10); /* Jump to the power on address. */ - printk(KERN_INFO "jumping to reset vector.\n"); + pr_info("jumping to reset vector.\n"); /* set high vectors (base at 0xbfc00000 */ set_c0_status(ST0_BEV | ST0_ERL); /* run uncached in kseg0 */ @@ -110,7 +110,7 @@ void bcm63xx_machine_reboot(void) if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1)) bcm6348_a1_reboot(); - printk(KERN_INFO "triggering watchdog soft-reset...\n"); + pr_info("triggering watchdog soft-reset...\n"); if (BCMCPU_IS_6328()) { bcm_wdt_writel(1, WDT_SOFTRESET_REG); } else { diff --git a/arch/mips/bcm63xx/timer.c b/arch/mips/bcm63xx/timer.c index 5f1135981568..2110359c00e5 100644 --- a/arch/mips/bcm63xx/timer.c +++ b/arch/mips/bcm63xx/timer.c @@ -195,7 +195,7 @@ int bcm63xx_timer_init(void) irq = bcm63xx_get_irq_number(IRQ_TIMER); ret = request_irq(irq, timer_interrupt, 0, "bcm63xx_timer", NULL); if (ret) { - printk(KERN_ERR "bcm63xx_timer: failed to register irq\n"); + pr_err("%s: failed to register irq\n", __func__); return ret; } From 5b24d52ce23d1c7a5c2bd884e57463e266eb8b85 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 12 Oct 2015 13:13:01 +0200 Subject: [PATCH 108/120] MIPS: Use USE_OF as the guard for appended dtb Since OF is now a user selectable symbol, the choice for appended dtb support should only be visible when USE_OF is selected, as this indicates actual machine support for device tree in MIPS. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: Kevin Cernekee Cc: Florian Fainelli Cc: Zubair Lutfullah Kakakhel Cc: James Hogan Cc: John Crispin Cc: Ganesan Ramalingam Cc: Jayachandran C Cc: Andrew Bresticker Cc: James Hartley Patchwork: https://patchwork.linux-mips.org/patch/11283/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 10feb1520b0c..8b8cd97cdff9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2705,7 +2705,7 @@ config BUILTIN_DTB bool choice - prompt "Kernel appended dtb support" if OF + prompt "Kernel appended dtb support" if USE_OF default MIPS_NO_APPENDED_DTB config MIPS_NO_APPENDED_DTB From 2024972ef5330dcae47f400c586764d8f4cb0b04 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 12 Oct 2015 13:13:02 +0200 Subject: [PATCH 109/120] MIPS: Make the kernel arguments from dtb available Similar to how arm allows using selecting between bootloader arguments, dtb arguments and both, allow to select them on mips. But since we have less control over the place of the dtb do not modify it but instead use the boot_command_line for merging them. The default is "use bootloader arguments" to keep the current behaviour as default. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: Kevin Cernekee Cc: Florian Fainelli Cc: Zubair Lutfullah Kakakhel Cc: James Hogan Cc: John Crispin Cc: Ganesan Ramalingam Cc: Jayachandran C Cc: Andrew Bresticker Cc: James Hartley Patchwork: https://patchwork.linux-mips.org/patch/11284/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 16 ++++++++++++++++ arch/mips/kernel/setup.c | 26 ++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8b8cd97cdff9..e3e65ae681c8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2749,6 +2749,22 @@ choice if you don't intend to always append a DTB. endchoice +choice + prompt "Kernel command line type" if !CMDLINE_OVERRIDE + default MIPS_CMDLINE_FROM_BOOTLOADER + + config MIPS_CMDLINE_FROM_DTB + depends on USE_OF + bool "Dtb kernel arguments if available" + + config MIPS_CMDLINE_DTB_EXTEND + depends on USE_OF + bool "Extend dtb kernel arguments with bootloader arguments" + + config MIPS_CMDLINE_FROM_BOOTLOADER + bool "Bootloader kernel arguments if available" +endchoice + endmenu config LOCKDEP_SUPPORT diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 5b46b672c939..6f142ee4a086 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -617,6 +617,10 @@ static void __init request_crashkernel(struct resource *res) } #endif /* !defined(CONFIG_KEXEC) */ +#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_EXTEND) + static void __init arch_mem_init(char **cmdline_p) { struct memblock_region *reg; @@ -641,18 +645,24 @@ static void __init arch_mem_init(char **cmdline_p) pr_info("Determined physical RAM map:\n"); print_memory_map(); -#ifdef CONFIG_CMDLINE_BOOL -#ifdef CONFIG_CMDLINE_OVERRIDE +#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); #else - if (builtin_cmdline[0]) { - strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); - strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE); + if ((USE_PROM_CMDLINE && arcs_cmdline[0]) || + (USE_DTB_CMDLINE && !boot_command_line[0])) + strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); + + if (EXTEND_WITH_PROM && arcs_cmdline[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); + strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); } - strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); #endif -#else - strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); #endif strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); From 2bcef9b457bbe159a5e3843e2578d8195e0b1c56 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 12 Oct 2015 13:13:03 +0200 Subject: [PATCH 110/120] MIPS: Make MIPS_CMDLINE_DTB default Seval of-enabled machines (bmips, lantiq, xlp, pistachio, ralink) copied the arguments from dtb to arcs_command_line to prevent the kernel from overwriting them. Since there is now an option to keep the dtb arguments, default to the new option remove the "backup" to arcs_command_line in case of USE_OF is enabled, except for those platforms that still take the bootloader arguments or do not use any at all. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: Kevin Cernekee Cc: Florian Fainelli Cc: Zubair Lutfullah Kakakhel Cc: James Hogan Cc: John Crispin Cc: Ganesan Ramalingam Cc: Jayachandran C Cc: Andrew Bresticker Cc: James Hartley Patchwork: https://patchwork.linux-mips.org/patch/11285/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 3 +++ arch/mips/bmips/setup.c | 1 - arch/mips/lantiq/prom.c | 2 -- arch/mips/netlogic/xlp/dt.c | 1 - arch/mips/pistachio/init.c | 1 - arch/mips/ralink/of.c | 2 -- 6 files changed, 3 insertions(+), 7 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e3e65ae681c8..a65341a03712 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2751,6 +2751,9 @@ endchoice choice prompt "Kernel command line type" if !CMDLINE_OVERRIDE + default MIPS_CMDLINE_FROM_DTB if USE_OF && !ATH79 && !MACH_INGENIC && \ + !MIPS_MALTA && !MIPS_SEAD3 && \ + !CAVIUM_OCTEON_SOC default MIPS_CMDLINE_FROM_BOOTLOADER config MIPS_CMDLINE_FROM_DTB diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index 526ec2789bb9..5b16d2955fbb 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -157,7 +157,6 @@ void __init plat_mem_setup(void) panic("no dtb found"); __dt_setup_arch(dtb); - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); for (q = bmips_quirk_list; q->quirk_fn; q++) { if (of_flat_dt_is_compatible(of_get_flat_dt_root(), diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index 0db099ecc016..297bcaa6b5d3 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -77,8 +77,6 @@ void __init plat_mem_setup(void) * parsed resulting in our memory appearing */ __dt_setup_arch(__dtb_start); - - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); } void __init device_tree_init(void) diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index a625bdb6d6aa..856a6e6d296e 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -87,7 +87,6 @@ void __init *xlp_dt_init(void *fdtp) void __init xlp_early_init_devtree(void) { __dt_setup_arch(xlp_fdt_blob); - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); } void __init device_tree_init(void) diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c index 8bd8ebb20a72..96ba2cc9ad3e 100644 --- a/arch/mips/pistachio/init.c +++ b/arch/mips/pistachio/init.c @@ -58,7 +58,6 @@ void __init plat_mem_setup(void) panic("Device-tree not present"); __dt_setup_arch((void *)fw_arg1); - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); plat_setup_iocoherency(); } diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 0d30dcd63246..f9eda5d8f82c 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -74,8 +74,6 @@ void __init plat_mem_setup(void) */ __dt_setup_arch(__dtb_start); - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); - of_scan_flat_dt(early_init_dt_find_memory, NULL); if (memory_dtb) of_scan_flat_dt(early_init_dt_scan_memory, NULL); From 26c188be1f99d609cd4946f97fdf9e29d3d5c81e Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Mon, 26 Oct 2015 11:30:54 +0000 Subject: [PATCH 111/120] dt-bindings: MIPS: Document xilfpga bindings and boot style Xilfpga boots only with device-tree. Document the required properties and the unique boot style Signed-off-by: Zubair Lutfullah Kakakhel Cc: robh+dt@kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11361/ Signed-off-by: Ralf Baechle --- .../devicetree/bindings/mips/img/xilfpga.txt | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/mips/img/xilfpga.txt diff --git a/Documentation/devicetree/bindings/mips/img/xilfpga.txt b/Documentation/devicetree/bindings/mips/img/xilfpga.txt new file mode 100644 index 000000000000..57e7ee942166 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/img/xilfpga.txt @@ -0,0 +1,83 @@ +Imagination University Program MIPSfpga +======================================= + +Under the Imagination University Program, a microAptiv UP core has been +released for academic usage. + +As we are dealing with a MIPS core instantiated on an FPGA, specifications +are fluid and can be varied in RTL. + +This binding document is provided as baseline guidance for the example +project provided by IMG. + +The example project runs on the Nexys4DDR board by Digilent powered by +the ARTIX-7 FPGA by Xilinx. + +Relevant details about the example project and the Nexys4DDR board: + +- microAptiv UP core m14Kc +- 50MHz clock speed +- 128Mbyte DDR RAM at 0x0000_0000 +- 8Kbyte RAM at 0x1000_0000 +- axi_intc at 0x1020_0000 +- axi_uart16550 at 0x1040_0000 +- axi_gpio at 0x1060_0000 +- axi_i2c at 0x10A0_0000 +- custom_gpio at 0x10C0_0000 +- axi_ethernetlite at 0x10E0_0000 +- 8Kbyte BootRAM at 0x1FC0_0000 + +Required properties: +-------------------- + - compatible: Must include "digilent,nexys4ddr","img,xilfpga". + +CPU nodes: +---------- +A "cpus" node is required. Required properties: + - #address-cells: Must be 1. + - #size-cells: Must be 0. +A CPU sub-node is also required for at least CPU 0. Required properties: + - device_type: Must be "cpu". + - compatible: Must be "mips,m14Kc". + - reg: Must be <0>. + - clocks: phandle to ext clock for fixed-clock received by MIPS core. + +Example: + + compatible = "img,xilfpga","digilent,nexys4ddr"; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "mips,m14Kc"; + reg = <0>; + clocks = <&ext>; + }; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + +Boot protocol: +-------------- + +The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000. +This is for easy reprogrammibility via JTAG. + +The BootRAM initializes the cache and the axi_uart peripheral. + +DDR initialization is already handled by a HW IP block. + +When the example project bitstream is loaded, the cpu_reset button +needs to be pressed. + +The bootram initializes the cache and axi_uart. +Then outputs MIPSFPGA\n\r on the serial port on the Nexys4DDR board. + +At this point, the board is ready to load the Linux kernel +vmlinux file via JTAG. From 552b8b363ede5fc53db343b67c0b2b5eaf783a11 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Mon, 26 Oct 2015 11:30:55 +0000 Subject: [PATCH 112/120] MIPS: xilfpga: Add xilfpga device tree files. Add device tree files for the MIPSfpga platform. See Documentation/devicetree/bindings/mips/img/xilfpga.txt for details about MIPSfpga Signed-off-by: Zubair Lutfullah Kakakhel Cc: robh+dt@kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11362/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/Makefile | 1 + arch/mips/boot/dts/xilfpga/Makefile | 9 +++++ arch/mips/boot/dts/xilfpga/microAptiv.dtsi | 21 ++++++++++ arch/mips/boot/dts/xilfpga/nexys4ddr.dts | 46 ++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 arch/mips/boot/dts/xilfpga/Makefile create mode 100644 arch/mips/boot/dts/xilfpga/microAptiv.dtsi create mode 100644 arch/mips/boot/dts/xilfpga/nexys4ddr.dts diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile index 778a34028c1b..0571ef7697b0 100644 --- a/arch/mips/boot/dts/Makefile +++ b/arch/mips/boot/dts/Makefile @@ -6,6 +6,7 @@ dts-dirs += mti dts-dirs += netlogic dts-dirs += qca dts-dirs += ralink +dts-dirs += xilfpga obj-y := $(addsuffix /, $(dts-dirs)) diff --git a/arch/mips/boot/dts/xilfpga/Makefile b/arch/mips/boot/dts/xilfpga/Makefile new file mode 100644 index 000000000000..913a752a9ff1 --- /dev/null +++ b/arch/mips/boot/dts/xilfpga/Makefile @@ -0,0 +1,9 @@ +dtb-$(CONFIG_XILFPGA_NEXYS4DDR) += nexys4ddr.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/xilfpga/microAptiv.dtsi b/arch/mips/boot/dts/xilfpga/microAptiv.dtsi new file mode 100644 index 000000000000..81d518e75785 --- /dev/null +++ b/arch/mips/boot/dts/xilfpga/microAptiv.dtsi @@ -0,0 +1,21 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "img,xilfpga"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "mips,m14Kc"; + clocks = <&ext>; + reg = <0>; + }; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; +}; diff --git a/arch/mips/boot/dts/xilfpga/nexys4ddr.dts b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts new file mode 100644 index 000000000000..686ebd11386d --- /dev/null +++ b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts @@ -0,0 +1,46 @@ +/dts-v1/; + +#include "microAptiv.dtsi" + +/ { + compatible = "digilent,nexys4ddr"; + + memory { + device_type = "memory"; + reg = <0x0 0x08000000>; + }; + + cpuintc: interrupt-controller@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + axi_gpio: gpio@10600000 { + #gpio-cells = <1>; + compatible = "xlnx,xps-gpio-1.00.a"; + gpio-controller; + reg = <0x10600000 0x10000>; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,gpio-width = <0x16>; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + } ; + + axi_uart16550: serial@10400000 { + compatible = "ns16550a"; + reg = <0x10400000 0x10000>; + + reg-shift = <2>; + reg-offset = <0x1000>; + + clocks = <&ext>; + }; +}; + +&ext { + clock-frequency = <50000000>; +}; From 9937f5fff889bde488c5ffd238dcb49e9b9cc7b7 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Mon, 26 Oct 2015 11:30:56 +0000 Subject: [PATCH 113/120] MIPS: xilfpga: Add mipsfpga platform code The xilfpga platform will be DT only. Add required platform code. DT files have already been added separately. Signed-off-by: Zubair Lutfullah Kakakhel Cc: robh+dt@kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11364/ Signed-off-by: Ralf Baechle --- arch/mips/Kbuild.platforms | 1 + arch/mips/Kconfig | 23 ++++++++++ arch/mips/include/asm/mach-xilfpga/irq.h | 18 ++++++++ arch/mips/xilfpga/Kconfig | 9 ++++ arch/mips/xilfpga/Makefile | 7 +++ arch/mips/xilfpga/Platform | 3 ++ arch/mips/xilfpga/init.c | 57 ++++++++++++++++++++++++ arch/mips/xilfpga/intc.c | 25 +++++++++++ arch/mips/xilfpga/time.c | 41 +++++++++++++++++ 9 files changed, 184 insertions(+) create mode 100644 arch/mips/include/asm/mach-xilfpga/irq.h create mode 100644 arch/mips/xilfpga/Kconfig create mode 100644 arch/mips/xilfpga/Makefile create mode 100644 arch/mips/xilfpga/Platform create mode 100644 arch/mips/xilfpga/init.c create mode 100644 arch/mips/xilfpga/intc.c create mode 100644 arch/mips/xilfpga/time.c diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index a424e46b50af..a96c81d1d22e 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -33,6 +33,7 @@ platforms += sibyte platforms += sni platforms += txx9 platforms += vr41xx +platforms += xilfpga # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index a65341a03712..218aa67a2c52 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -404,6 +404,28 @@ config MACH_PISTACHIO help This enables support for the IMG Pistachio SoC platform. +config MACH_XILFPGA + bool "MIPSfpga Xilinx based boards" + select ARCH_REQUIRE_GPIOLIB + select BOOT_ELF32 + select BOOT_RAW + select BUILTIN_DTB + select CEVT_R4K + select COMMON_CLK + select CSRC_R4K + select IRQ_MIPS_CPU + select LIBFDT + select MIPS_CPU_SCACHE + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_ZBOOT_UART16550 + select USE_OF + select USE_GENERIC_EARLY_PRINTK_8250 + help + This enables support for the IMG University Program MIPSfpga platform. + config MIPS_MALTA bool "MIPS Malta board" select ARCH_MAY_HAVE_PC_FDC @@ -970,6 +992,7 @@ source "arch/mips/loongson32/Kconfig" source "arch/mips/loongson64/Kconfig" source "arch/mips/netlogic/Kconfig" source "arch/mips/paravirt/Kconfig" +source "arch/mips/xilfpga/Kconfig" endmenu diff --git a/arch/mips/include/asm/mach-xilfpga/irq.h b/arch/mips/include/asm/mach-xilfpga/irq.h new file mode 100644 index 000000000000..0132a5b91f57 --- /dev/null +++ b/arch/mips/include/asm/mach-xilfpga/irq.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Zubair Lutfullah Kakakhel + * + * 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 __MIPS_ASM_MACH_XILFPGA_IRQ_H__ +#define __MIPS_ASM_MACH_XILFPGA_IRQ_H__ + +#define NR_IRQS 32 + +#include_next + +#endif /* __MIPS_ASM_MACH_XILFPGA_IRQ_H__ */ diff --git a/arch/mips/xilfpga/Kconfig b/arch/mips/xilfpga/Kconfig new file mode 100644 index 000000000000..42a030a0edba --- /dev/null +++ b/arch/mips/xilfpga/Kconfig @@ -0,0 +1,9 @@ +choice + prompt "Machine type" + depends on MACH_XILFPGA + default XILFPGA_NEXYS4DDR + +config XILFPGA_NEXYS4DDR + bool "Nexys4DDR by Digilent" + +endchoice diff --git a/arch/mips/xilfpga/Makefile b/arch/mips/xilfpga/Makefile new file mode 100644 index 000000000000..a4deec6fadbc --- /dev/null +++ b/arch/mips/xilfpga/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Xilfpga +# + +obj-y += init.o +obj-y += intc.o +obj-y += time.o diff --git a/arch/mips/xilfpga/Platform b/arch/mips/xilfpga/Platform new file mode 100644 index 000000000000..ed375afe3d39 --- /dev/null +++ b/arch/mips/xilfpga/Platform @@ -0,0 +1,3 @@ +platform-$(CONFIG_MACH_XILFPGA) += xilfpga/ +cflags-$(CONFIG_MACH_XILFPGA) += -I$(srctree)/arch/mips/include/asm/mach-xilfpga +load-$(CONFIG_MACH_XILFPGA) += 0xffffffff80100000 diff --git a/arch/mips/xilfpga/init.c b/arch/mips/xilfpga/init.c new file mode 100644 index 000000000000..ce2aee2169ac --- /dev/null +++ b/arch/mips/xilfpga/init.c @@ -0,0 +1,57 @@ +/* + * Xilfpga platform setup + * + * Copyright (C) 2015 Imagination Technologies + * Author: Zubair Lutfullah Kakakhel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include + +#include + +#define XILFPGA_UART_BASE 0xb0401000 + +const char *get_system_type(void) +{ + return "MIPSfpga"; +} + +void __init plat_mem_setup(void) +{ + __dt_setup_arch(__dtb_start); + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); +} + +void __init prom_init(void) +{ + setup_8250_early_printk_port(XILFPGA_UART_BASE, 2, 50000); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init device_tree_init(void) +{ + if (!initial_boot_params) + return; + + unflatten_and_copy_device_tree(); +} + +static int __init plat_of_setup(void) +{ + if (!of_have_populated_dt()) + panic("Device tree not present"); + + if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)) + panic("Failed to populate DT"); + + return 0; +} +arch_initcall(plat_of_setup); diff --git a/arch/mips/xilfpga/intc.c b/arch/mips/xilfpga/intc.c new file mode 100644 index 000000000000..c4d1a716b347 --- /dev/null +++ b/arch/mips/xilfpga/intc.c @@ -0,0 +1,25 @@ +/* + * Xilfpga interrupt controller setup + * + * Copyright (C) 2015 Imagination Technologies + * Author: Zubair Lutfullah Kakakhel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include + +#include + +static struct of_device_id of_irq_ids[] __initdata = { + { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init }, + {}, +}; + +void __init arch_init_irq(void) +{ + of_irq_init(of_irq_ids); +} diff --git a/arch/mips/xilfpga/time.c b/arch/mips/xilfpga/time.c new file mode 100644 index 000000000000..a1c0fc8893e8 --- /dev/null +++ b/arch/mips/xilfpga/time.c @@ -0,0 +1,41 @@ +/* + * Xilfpga clocksource/timer setup + * + * Copyright (C) 2015 Imagination Technologies + * Author: Zubair Lutfullah Kakakhel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include + +void __init plat_time_init(void) +{ + struct device_node *np; + struct clk *clk; + + of_clk_init(NULL); + clocksource_of_init(); + + 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; + } + + mips_hpt_frequency = clk_get_rate(clk) / 2; + clk_put(clk); +} From 834cc15b443840d94e225bb0ff0604b1c1f6f2e1 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Mon, 26 Oct 2015 11:30:57 +0000 Subject: [PATCH 114/120] MIPS: Add xilfpga defconfig Add defconfig for MIPSfpga Signed-off-by: Zubair Lutfullah Kakakhel Cc: robh+dt@kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11363/ Signed-off-by: Ralf Baechle --- arch/mips/configs/xilfpga_defconfig | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 arch/mips/configs/xilfpga_defconfig diff --git a/arch/mips/configs/xilfpga_defconfig b/arch/mips/configs/xilfpga_defconfig new file mode 100644 index 000000000000..ed1dce348320 --- /dev/null +++ b/arch/mips/configs/xilfpga_defconfig @@ -0,0 +1,40 @@ +CONFIG_MACH_XILFPGA=y +# CONFIG_COMPACTION is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_BLOCK is not set +# CONFIG_SUSPEND is not set +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_UNIX98_PTYS is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_XILINX=y +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MIPS_PLATFORM_DEVICES is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_PROC_PAGE_MONITOR is not set +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_PANIC_ON_OOPS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,115200" From 997effa0c198ab3b7d4b62cf443d797e4e0bf5ff Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 16 Oct 2015 12:51:58 -0700 Subject: [PATCH 115/120] MIPS: BMIPS: Enable GZIP ramdisk and timed printks Update bmips_be_defconfig and bmips_stb_defconfig to have GZIP ramdisk support enabled by default as well was timed printks. Signed-off-by: Florian Fainelli Reviewed-by: Kevin Cernekee Reviewed-by: Dragan Stancevic Cc: linux-mips@linux-mips.org Cc: blogic@openwrt.org Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/11307/ Signed-off-by: Ralf Baechle --- arch/mips/configs/bmips_be_defconfig | 3 ++- arch/mips/configs/bmips_stb_defconfig | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/mips/configs/bmips_be_defconfig b/arch/mips/configs/bmips_be_defconfig index f5585c8f35ad..24dcb90b0f64 100644 --- a/arch/mips/configs/bmips_be_defconfig +++ b/arch/mips/configs/bmips_be_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y # CONFIG_SWAP is not set CONFIG_NO_HZ=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_RD_GZIP is not set +CONFIG_RD_GZIP=y CONFIG_EXPERT=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set @@ -33,6 +33,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_PRINTK_TIME=y CONFIG_BRCMSTB_GISB_ARB=y CONFIG_MTD=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/bmips_stb_defconfig b/arch/mips/configs/bmips_stb_defconfig index 400a47ec1ef1..4eb5d6e9cf8f 100644 --- a/arch/mips/configs/bmips_stb_defconfig +++ b/arch/mips/configs/bmips_stb_defconfig @@ -9,7 +9,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y # CONFIG_SWAP is not set CONFIG_NO_HZ=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_RD_GZIP is not set +CONFIG_RD_GZIP=y CONFIG_EXPERT=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set @@ -34,6 +34,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_PRINTK_TIME=y CONFIG_BRCMSTB_GISB_ARB=y CONFIG_MTD=y CONFIG_MTD_CFI=y From 22b14523994588279ae9c5ccfe64073c1e5b3c00 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 9 Oct 2015 20:56:28 -0400 Subject: [PATCH 116/120] MIPS: Fix PAGE_MASK definition Make PAGE_MASK an unsigned long, like it is on x86, to avoid: In file included from arch/mips/kernel/asm-offsets.c:14:0: include/linux/mm.h: In function '__pfn_to_pfn_t': include/linux/mm.h:1050:2: warning: left shift count >= width of type pfn_t pfn_t = { .val = pfn | (flags & PFN_FLAGS_MASK), }; ...where PFN_FLAGS_MASK is: #define PFN_FLAGS_MASK (~PAGE_MASK << (BITS_PER_LONG - PAGE_SHIFT)) Signed-off-by: Dan Williams Cc: ross.zwisler@linux.intel.com Cc: hch@lst.de Cc: linux-mips@linux-mips.org Cc: linux-nvdimm@lists.01.org Cc: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org Patchwork: https://patchwork.linux-mips.org/patch/11280/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/page.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 89dd7fed1a57..ad1fccdb8d13 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -33,7 +33,7 @@ #define PAGE_SHIFT 16 #endif #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +#define PAGE_MASK (~(PAGE_SIZE - 1)) /* * This is used for calculating the real page sizes From d00d920338382ceaefc643760daf9936ae9c5788 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 5 Nov 2015 00:50:24 +0000 Subject: [PATCH 117/120] MIPS: Clean up compat_siginfo_t While mips can't use the generic compat_siginfo_t directly because its si_code and si_errno are inverted, we can still make it as close to the generic version as possible. This makes it easier to update when new members are added to siginfo_t. The main changes are adding a missing _sigsys union member and eliminating the unused _irix_sigchld one. Signed-off-by: Amanieu d'Antras Cc: linux-kernel@vger.kernel.org Cc: Oleg Nesterov Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11455/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/compat.h | 74 ++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index c4bd54a7f5ce..a9580097cba8 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -130,6 +130,8 @@ typedef union compat_sigval { compat_uptr_t sival_ptr; } compat_sigval_t; +/* Can't use the generic version because si_code and si_errno are swapped */ + #define SI_PAD_SIZE32 (128/sizeof(int) - 3) typedef struct compat_siginfo { @@ -138,57 +140,61 @@ typedef struct compat_siginfo { int si_errno; union { - int _pad[SI_PAD_SIZE32]; + int _pad[128 / sizeof(int) - 3]; /* kill() */ struct { compat_pid_t _pid; /* sender's pid */ - __compat_uid_t _uid; /* sender's uid */ + __compat_uid32_t _uid; /* sender's uid */ } _kill; - /* SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - __compat_uid_t _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* IRIX SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - compat_clock_t _utime; - int _status; /* exit code */ - compat_clock_t _stime; - } _irix_sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ - struct { - s32 _addr; /* faulting insn/memory ref. */ - } _sigfault; - - /* SIGPOLL, SIGXFSZ (To do ...) */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - /* POSIX.1b timers */ struct { - timer_t _tid; /* timer id */ + compat_timer_t _tid; /* timer id */ int _overrun; /* overrun count */ - compat_sigval_t _sigval;/* same as below */ - int _sys_private; /* not to be passed to user */ + compat_sigval_t _sigval; /* same as below */ } _timer; /* POSIX.1b signals */ struct { compat_pid_t _pid; /* sender's pid */ - __compat_uid_t _uid; /* sender's uid */ + __compat_uid32_t _uid; /* sender's uid */ compat_sigval_t _sigval; } _rt; + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + __compat_uid32_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + compat_uptr_t _addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_TRAPNO + int _trapno; /* TRAP # which caused the signal */ +#endif + short _addr_lsb; /* LSB of the reported address */ + struct { + compat_uptr_t _lower; + compat_uptr_t _upper; + } _addr_bnd; + } _sigfault; + + /* SIGPOLL */ + struct { + compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + + struct { + compat_uptr_t _call_addr; /* calling insn */ + int _syscall; /* triggering system call number */ + compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */ + } _sigsys; } _sifields; } compat_siginfo_t; From 87db537da4cd1bfad388511a3647bbb497d2fb61 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 11 Sep 2015 17:46:14 +0300 Subject: [PATCH 118/120] MIPS: vmlinux: create a section for appended DTB For bootloaders that support booting only ELF kernels and load only ELF segments to memory there is no easy way to supply DTB without kernel recompilation. For that purpose, create a section called .appended_dtb that can be later updated with board-specific DTB using binutils e.g. at kernel installation time. Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11114/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 14 ++++++++++++++ arch/mips/kernel/setup.c | 4 ++++ arch/mips/kernel/vmlinux.lds.S | 5 +++++ 3 files changed, 23 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 218aa67a2c52..71683a853372 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2736,6 +2736,20 @@ choice help Do not enable appended dtb support. + config MIPS_ELF_APPENDED_DTB + bool "vmlinux" + help + With this option, the boot code will look for a device tree binary + DTB) included in the vmlinux ELF section .appended_dtb. By default + it is empty and the DTB can be appended using binutils command + objcopy: + + objcopy --update-section .appended_dtb=.dtb vmlinux + + This is meant as a backward compatiblity convenience for those + systems with a bootloader that can't be upgraded to accommodate + the documented boot protocol using a device tree. + config MIPS_RAW_APPENDED_DTB bool "vmlinux.bin" help diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 6f142ee4a086..66aac55df349 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -39,6 +39,10 @@ #include #include +#ifdef CONFIG_MIPS_ELF_APPENDED_DTB +const char __section(.appended_dtb) __appended_dtb[0x100000]; +#endif /* CONFIG_MIPS_ELF_APPENDED_DTB */ + struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_data); diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 07d32a4aea60..f4c23d9023be 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -132,6 +132,11 @@ SECTIONS __appended_dtb = .; /* leave space for appended DTB */ . += 0x100000; +#elif defined(CONFIG_MIPS_ELF_APPENDED_DTB) + .appended_dtb : AT(ADDR(.appended_dtb) - LOAD_OFFSET) { + *(.appended_dtb) + KEEP(*(.appended_dtb)) + } #endif /* * Align to 64K in attempt to eliminate holes before the From 651d19fb10fac0f1f25c028c8e46ded9fc43a640 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 11 Sep 2015 17:46:15 +0300 Subject: [PATCH 119/120] MIPS: Octeon: Support APPENDED_DTB Use appended DTB when available. Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11115/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index bd634259eab9..cd7101fb6227 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1081,6 +1081,7 @@ void __init prom_free_prom_memory(void) int octeon_prune_device_tree(void); +extern const char __appended_dtb; extern const char __dtb_octeon_3xxx_begin; extern const char __dtb_octeon_68xx_begin; void __init device_tree_init(void) @@ -1088,11 +1089,19 @@ void __init device_tree_init(void) const void *fdt; bool do_prune; +#ifdef CONFIG_MIPS_ELF_APPENDED_DTB + if (!fdt_check_header(&__appended_dtb)) { + fdt = &__appended_dtb; + do_prune = false; + pr_info("Using appended Device Tree.\n"); + } else +#endif if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { fdt = phys_to_virt(octeon_bootinfo->fdt_addr); if (fdt_check_header(fdt)) panic("Corrupt Device Tree passed to kernel."); do_prune = false; + pr_info("Using passed Device Tree.\n"); } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { fdt = &__dtb_octeon_68xx_begin; do_prune = true; @@ -1106,8 +1115,6 @@ void __init device_tree_init(void) if (do_prune) { octeon_prune_device_tree(); pr_info("Using internal Device Tree.\n"); - } else { - pr_info("Using passed Device Tree.\n"); } unflatten_and_copy_device_tree(); } From bf463f2f7510771db180908507005379850dade0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 5 Sep 2015 18:47:31 +0200 Subject: [PATCH 120/120] MIPS: idle: add case for CPU_5KE While the 5KE processors have never been taped out, they exists though a CP0.PRId and experimental RTLs or QEMU implementations. Add a case entry in the idle code, as they can use the standard idle loop like the 5K processors. Signed-off-by: Aurelien Jarno Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11099/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/idle.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 3e2b0b6c3b08..35af61530de1 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -165,6 +165,7 @@ void __init check_wait(void) case CPU_4KEC: case CPU_4KSC: case CPU_5KC: + case CPU_5KE: case CPU_25KF: case CPU_PR4450: case CPU_BMIPS3300: