Merge tag 'sh-for-4.8' of git://git.libc.org/linux-sh

Pull arch/sh updates from Rich Felker:
 "These changes improve device tree support (including builtin DTB), add
  support for the J-Core J2 processor, an open source synthesizable
  reimplementation of the SH-2 ISA, resolve a longstanding sigcontext
  ABI mismatch issue, and fix various bugs including nommu-specific
  issues and minor regressions introduced in 4.6.

  The J-Core arch support is included here but to be usable it needs
  drivers that are waiting on approval/inclusion from their subsystem
  maintainers"

* tag 'sh-for-4.8' of git://git.libc.org/linux-sh: (23 commits)
  sh: add device tree source for J2 FPGA on Mimas v2 board
  sh: add defconfig for J-Core J2
  sh: use common clock framework with device tree boards
  sh: system call wire up
  sh: Delete unnecessary checks before the function call "mempool_destroy"
  sh: do not perform IPI-based cache flush except on boards that need it
  sh: add SMP support for J2
  sh: SMP support for SH2 entry.S
  sh: add working futex atomic ops on userspace addresses for smp
  sh: add J2 atomics using the cas.l instruction
  sh: add AT_HWCAP flag for J-Core cas.l instruction
  sh: add support for J-Core J2 processor
  sh: fix build regression with CONFIG_OF && !CONFIG_OF_FLATTREE
  sh: allow clocksource drivers to register sched_clock backends
  sh: make heartbeat driver explicitly non-modular
  sh: make board-secureedge5410 explicitly non-modular
  sh: make mm/asids-debugfs explicitly non-modular
  sh: make time.c explicitly non-modular
  sh: fix futex/robust_list on nommu models
  sh: disable aliased page logic on NOMMU models
  ...
This commit is contained in:
Linus Torvalds
2016-08-06 09:00:05 -04:00
45 changed files with 1223 additions and 416 deletions

View File

@@ -24,11 +24,13 @@ int __init clk_init(void)
{
int ret;
#ifndef CONFIG_COMMON_CLK
ret = arch_clk_init();
if (unlikely(ret)) {
pr_err("%s: CPU clock registration failed.\n", __func__);
return ret;
}
#endif
if (sh_mv.mv_clk_init) {
ret = sh_mv.mv_clk_init();
@@ -39,11 +41,13 @@ int __init clk_init(void)
}
}
#ifndef CONFIG_COMMON_CLK
/* Kick the child clocks.. */
recalculate_root_clocks();
/* Enable the necessary init clocks */
clk_enable_init_clocks();
#endif
return ret;
}

View File

@@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void)
/*
* Generic first-level cache init
*/
#ifdef CONFIG_SUPERH32
#if defined(CONFIG_SUPERH32) && !defined(CONFIG_CPU_J2)
static void cache_init(void)
{
unsigned long ccr, flags;
@@ -323,9 +323,13 @@ asmlinkage void cpu_init(void)
cache_init();
if (raw_smp_processor_id() == 0) {
#ifdef CONFIG_MMU
shm_align_mask = max_t(unsigned long,
current_cpu_data.dcache.way_size - 1,
PAGE_SIZE - 1);
#else
shm_align_mask = PAGE_SIZE - 1;
#endif
/* Boot CPU sets the cache shape */
detect_cache_shape();

View File

@@ -27,6 +27,7 @@ static const char *cpu_name[] = {
[CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
[CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
[CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
[CPU_J2] = "J2",
[CPU_SH_NONE] = "Unknown"
};

View File

@@ -5,3 +5,7 @@
obj-y := ex.o probe.o entry.o
obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
# SMP setup
smp-$(CONFIG_CPU_J2) := smp-j2.o
obj-$(CONFIG_SMP) += $(smp-y)

View File

@@ -47,6 +47,13 @@ ENTRY(exception_handler)
mov.l r3,@-sp
cli
mov.l $cpu_mode,r2
#ifdef CONFIG_SMP
mov.l $cpuid,r3
mov.l @r3,r3
mov.l @r3,r3
shll2 r3
add r3,r2
#endif
mov.l @r2,r0
mov.l @(5*4,r15),r3 ! previous SR
or r0,r3 ! set MD
@@ -57,6 +64,13 @@ ENTRY(exception_handler)
mov.l __md_bit,r0
mov.l r0,@r2 ! enter kernel mode
mov.l $current_thread_info,r2
#ifdef CONFIG_SMP
mov.l $cpuid,r0
mov.l @r0,r0
mov.l @r0,r0
shll2 r0
add r0,r2
#endif
mov.l @r2,r2
mov #(THREAD_SIZE >> 8),r0
shll8 r0
@@ -147,6 +161,11 @@ ENTRY(exception_handler)
mov #31,r8
cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 31 is trap
#ifdef CONFIG_CPU_J2
mov #16,r8
cmp/hs r8,r9
bt interrupt_entry ! 31 > vec >= 16 is interrupt
#endif
mov.l 4f,r8
mov r9,r4
@@ -260,6 +279,13 @@ restore_all:
lds.l @r0+,macl
mov r15,r0
mov.l $cpu_mode,r2
#ifdef CONFIG_SMP
mov.l $cpuid,r3
mov.l @r3,r3
mov.l @r3,r3
shll2 r3
add r3,r2
#endif
mov #OFF_SR,r3
mov.l @(r0,r3),r1
mov.l __md_bit,r3
@@ -276,6 +302,13 @@ restore_all:
mov.l r1,@r2 ! set pc
get_current_thread_info r0, r1
mov.l $current_thread_info,r1
#ifdef CONFIG_SMP
mov.l $cpuid,r3
mov.l @r3,r3
mov.l @r3,r3
shll2 r3
add r3,r1
#endif
mov.l r0,@r1
mov.l @r15+,r0
mov.l @r15+,r1
@@ -303,19 +336,41 @@ $current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
#ifdef CONFIG_SMP
$cpuid:
.long sh2_cpuid_addr
#endif
! common exception handler
#include "../../entry-common.S"
#ifdef CONFIG_NR_CPUS
#define NR_CPUS CONFIG_NR_CPUS
#else
#define NR_CPUS 1
#endif
.data
! cpu operation mode
! bit30 = MD (compatible SH3/4)
__cpu_mode:
.rept NR_CPUS
.long 0x40000000
.endr
#ifdef CONFIG_SMP
.global sh2_cpuid_addr
sh2_cpuid_addr:
.long dummy_cpuid
dummy_cpuid:
.long 0
#endif
.section .bss
__current_thread_info:
.rept NR_CPUS
.long 0
.endr
ENTRY(exception_handling_table)
.space 4*32

View File

@@ -10,10 +10,27 @@
* for more details.
*/
#include <linux/init.h>
#include <linux/of_fdt.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/processor.h>
#include <asm/cache.h>
void cpu_probe(void)
#if defined(CONFIG_CPU_J2)
extern u32 __iomem *j2_ccr_base;
static int __init scan_cache(unsigned long node, const char *uname,
int depth, void *data)
{
if (!of_flat_dt_is_compatible(node, "jcore,cache"))
return 0;
j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node);
return 1;
}
#endif
void __ref cpu_probe(void)
{
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
boot_cpu_data.type = CPU_SH7619;
@@ -24,10 +41,30 @@ void cpu_probe(void)
boot_cpu_data.dcache.linesz = L1_CACHE_BYTES;
boot_cpu_data.dcache.flags = 0;
#endif
#if defined(CONFIG_CPU_J2)
unsigned cpu = hard_smp_processor_id();
if (cpu == 0) of_scan_flat_dt(scan_cache, NULL);
if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu);
if (cpu != 0) return;
boot_cpu_data.type = CPU_J2;
/* These defaults are appropriate for the original/current
* J2 cache. Once there is a proper framework for getting cache
* info from device tree, we should switch to that. */
boot_cpu_data.dcache.ways = 1;
boot_cpu_data.dcache.sets = 256;
boot_cpu_data.dcache.entry_shift = 5;
boot_cpu_data.dcache.linesz = 32;
boot_cpu_data.dcache.flags = 0;
boot_cpu_data.flags |= CPU_HAS_CAS_L;
#else
/*
* SH-2 doesn't have separate caches
*/
boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
#endif
boot_cpu_data.icache = boot_cpu_data.dcache;
boot_cpu_data.family = CPU_FAMILY_SH2;
}

View File

@@ -0,0 +1,139 @@
/*
* SMP support for J2 processor
*
* Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
*
* 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.
*/
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/cmpxchg.h>
DEFINE_PER_CPU(unsigned, j2_ipi_messages);
extern u32 *sh2_cpuid_addr;
static u32 *j2_ipi_trigger;
static int j2_ipi_irq;
static irqreturn_t j2_ipi_interrupt_handler(int irq, void *arg)
{
unsigned cpu = hard_smp_processor_id();
volatile unsigned *pmsg = &per_cpu(j2_ipi_messages, cpu);
unsigned messages, i;
do messages = *pmsg;
while (cmpxchg(pmsg, messages, 0) != messages);
if (!messages) return IRQ_NONE;
for (i=0; i<SMP_MSG_NR; i++)
if (messages & (1U<<i))
smp_message_recv(i);
return IRQ_HANDLED;
}
static void j2_smp_setup(void)
{
}
static void j2_prepare_cpus(unsigned int max_cpus)
{
struct device_node *np;
unsigned i, max = 1;
np = of_find_compatible_node(NULL, NULL, "jcore,ipi-controller");
if (!np)
goto out;
j2_ipi_irq = irq_of_parse_and_map(np, 0);
j2_ipi_trigger = of_iomap(np, 0);
if (!j2_ipi_irq || !j2_ipi_trigger)
goto out;
np = of_find_compatible_node(NULL, NULL, "jcore,cpuid-mmio");
if (!np)
goto out;
sh2_cpuid_addr = of_iomap(np, 0);
if (!sh2_cpuid_addr)
goto out;
if (request_irq(j2_ipi_irq, j2_ipi_interrupt_handler, IRQF_PERCPU,
"ipi", (void *)j2_ipi_interrupt_handler) != 0)
goto out;
max = max_cpus;
out:
/* Disable any cpus past max_cpus, or all secondaries if we didn't
* get the necessary resources to support SMP. */
for (i=max; i<NR_CPUS; i++) {
set_cpu_possible(i, false);
set_cpu_present(i, false);
}
}
static void j2_start_cpu(unsigned int cpu, unsigned long entry_point)
{
struct device_node *np;
u32 regs[2];
void __iomem *release, *initpc;
if (!cpu) return;
np = of_get_cpu_node(cpu, NULL);
if (!np) return;
if (of_property_read_u32_array(np, "cpu-release-addr", regs, 2)) return;
release = ioremap_nocache(regs[0], sizeof(u32));
initpc = ioremap_nocache(regs[1], sizeof(u32));
__raw_writel(entry_point, initpc);
__raw_writel(1, release);
iounmap(initpc);
iounmap(release);
pr_info("J2 SMP: requested start of cpu %u\n", cpu);
}
static unsigned int j2_smp_processor_id(void)
{
return __raw_readl(sh2_cpuid_addr);
}
static void j2_send_ipi(unsigned int cpu, unsigned int message)
{
volatile unsigned *pmsg;
unsigned old;
unsigned long val;
/* There is only one IPI interrupt shared by all messages, so
* we keep a separate interrupt flag per message type in sw. */
pmsg = &per_cpu(j2_ipi_messages, cpu);
do old = *pmsg;
while (cmpxchg(pmsg, old, old|(1U<<message)) != old);
/* Generate the actual interrupt by writing to CCRn bit 28. */
val = __raw_readl(j2_ipi_trigger + cpu);
__raw_writel(val | (1U<<28), j2_ipi_trigger + cpu);
}
static struct plat_smp_ops j2_smp_ops = {
.smp_setup = j2_smp_setup,
.prepare_cpus = j2_prepare_cpus,
.start_cpu = j2_start_cpu,
.smp_processor_id = j2_smp_processor_id,
.send_ipi = j2_send_ipi,
.cpu_die = native_cpu_die,
.cpu_disable = native_cpu_disable,
.play_dead = native_play_dead,
};
CPU_METHOD_OF_DECLARE(j2_cpu_method, "jcore,spin-table", &j2_smp_ops);

View File

@@ -1009,10 +1009,8 @@ static void __init dwarf_unwinder_cleanup(void)
rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node)
kfree(cie);
if (dwarf_reg_pool)
mempool_destroy(dwarf_reg_pool);
if (dwarf_frame_pool)
mempool_destroy(dwarf_frame_pool);
mempool_destroy(dwarf_reg_pool);
mempool_destroy(dwarf_frame_pool);
kmem_cache_destroy(dwarf_reg_cachep);
kmem_cache_destroy(dwarf_frame_cachep);
}

View File

@@ -67,7 +67,7 @@ ENTRY(_stext)
ldc r0, r6_bank
#endif
#ifdef CONFIG_OF
#ifdef CONFIG_OF_FLATTREE
mov r4, r12 ! Store device tree blob pointer in r12
#endif
@@ -318,7 +318,7 @@ ENTRY(_stext)
10:
#endif
#ifdef CONFIG_OF
#ifdef CONFIG_OF_FLATTREE
mov.l 8f, r0 ! Make flat device tree available early.
jsr @r0
mov r12, r4
@@ -349,7 +349,7 @@ ENTRY(stack_start)
5: .long start_kernel
6: .long cpu_init
7: .long init_thread_union
#if defined(CONFIG_OF)
#if defined(CONFIG_OF_FLATTREE)
8: .long sh_fdt_init
#endif

View File

@@ -242,7 +242,7 @@ void __init __weak plat_early_device_setup(void)
{
}
#ifdef CONFIG_OF
#ifdef CONFIG_OF_FLATTREE
void __ref sh_fdt_init(phys_addr_t dt_phys)
{
static int done = 0;
@@ -251,7 +251,11 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
/* Avoid calling an __init function on secondary cpus. */
if (done) return;
#ifdef CONFIG_USE_BUILTIN_DTB
dt_virt = __dtb_start;
#else
dt_virt = phys_to_virt(dt_phys);
#endif
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
pr_crit("Error: invalid device tree blob"

View File

@@ -386,3 +386,17 @@ ENTRY(sys_call_table)
.long sys_process_vm_writev
.long sys_kcmp
.long sys_finit_module
.long sys_sched_getattr
.long sys_sched_setattr /* 370 */
.long sys_renameat2
.long sys_seccomp
.long sys_getrandom
.long sys_memfd_create
.long sys_bpf /* 375 */
.long sys_execveat
.long sys_userfaultfd
.long sys_membarrier
.long sys_mlock2
.long sys_copy_file_range /* 380 */
.long sys_preadv2
.long sys_pwritev2

View File

@@ -406,3 +406,17 @@ sys_call_table:
.long sys_process_vm_writev
.long sys_kcmp
.long sys_finit_module
.long sys_sched_getattr /* 380 */
.long sys_sched_setattr
.long sys_renameat2
.long sys_seccomp
.long sys_getrandom
.long sys_memfd_create /* 385 */
.long sys_bpf
.long sys_execveat
.long sys_userfaultfd
.long sys_membarrier
.long sys_mlock2 /* 390 */
.long sys_copy_file_range
.long sys_preadv2
.long sys_pwritev2

View File

@@ -11,7 +11,6 @@
* for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/profile.h>
#include <linux/timex.h>
@@ -90,7 +89,7 @@ static int __init rtc_generic_init(void)
return PTR_ERR_OR_ZERO(pdev);
}
module_init(rtc_generic_init);
device_initcall(rtc_generic_init);
void (*board_time_init)(void);