1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun * 3*4882a593Smuzhiyun * SMP support for R-Mobile / SH-Mobile 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2010 Magnus Damm 6*4882a593Smuzhiyun * Copyright (C) 2010 Takashi Yoshii 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * Based on vexpress, Copyright (c) 2003 ARM Limited, All Rights Reserved 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun#include <linux/init.h> 11*4882a593Smuzhiyun#include <linux/linkage.h> 12*4882a593Smuzhiyun#include <linux/threads.h> 13*4882a593Smuzhiyun#include <asm/assembler.h> 14*4882a593Smuzhiyun#include <asm/memory.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun#define SCTLR_MMU 0x01 17*4882a593Smuzhiyun#define BOOTROM_ADDRESS 0xE6340000 18*4882a593Smuzhiyun#define RWTCSRA_ADDRESS 0xE6020004 19*4882a593Smuzhiyun#define RWTCSRA_WOVF 0x10 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun/* 22*4882a593Smuzhiyun * Reset vector for secondary CPUs. 23*4882a593Smuzhiyun * This will be mapped at address 0 by SBAR register. 24*4882a593Smuzhiyun * We need _long_ jump to the physical address. 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun .arm 27*4882a593Smuzhiyun .align 12 28*4882a593SmuzhiyunENTRY(shmobile_boot_vector) 29*4882a593Smuzhiyun ldr r1, 1f 30*4882a593Smuzhiyun bx r1 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunENDPROC(shmobile_boot_vector) 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun .align 2 35*4882a593Smuzhiyun .globl shmobile_boot_fn 36*4882a593Smuzhiyunshmobile_boot_fn: 37*4882a593Smuzhiyun1: .space 4 38*4882a593Smuzhiyun .globl shmobile_boot_size 39*4882a593Smuzhiyunshmobile_boot_size: 40*4882a593Smuzhiyun .long . - shmobile_boot_vector 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun#ifdef CONFIG_ARCH_RCAR_GEN2 43*4882a593Smuzhiyun/* 44*4882a593Smuzhiyun * Reset vector for R-Car Gen2 and RZ/G1 secondary CPUs. 45*4882a593Smuzhiyun * This will be mapped at address 0 by SBAR register. 46*4882a593Smuzhiyun */ 47*4882a593SmuzhiyunENTRY(shmobile_boot_vector_gen2) 48*4882a593Smuzhiyun mrc p15, 0, r0, c0, c0, 5 @ r0 = MPIDR 49*4882a593Smuzhiyun ldr r1, shmobile_boot_cpu_gen2 50*4882a593Smuzhiyun cmp r0, r1 51*4882a593Smuzhiyun bne shmobile_smp_continue_gen2 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun mrc p15, 0, r1, c1, c0, 0 @ r1 = SCTLR 54*4882a593Smuzhiyun and r0, r1, #SCTLR_MMU 55*4882a593Smuzhiyun cmp r0, #SCTLR_MMU 56*4882a593Smuzhiyun beq shmobile_smp_continue_gen2 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun ldr r0, rwtcsra 59*4882a593Smuzhiyun mov r1, #0 60*4882a593Smuzhiyun ldrb r1, [r0] 61*4882a593Smuzhiyun and r0, r1, #RWTCSRA_WOVF 62*4882a593Smuzhiyun cmp r0, #RWTCSRA_WOVF 63*4882a593Smuzhiyun bne shmobile_smp_continue_gen2 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun ldr r0, bootrom 66*4882a593Smuzhiyun bx r0 67*4882a593Smuzhiyun 68*4882a593Smuzhiyunshmobile_smp_continue_gen2: 69*4882a593Smuzhiyun ldr r1, shmobile_boot_fn_gen2 70*4882a593Smuzhiyun bx r1 71*4882a593Smuzhiyun 72*4882a593SmuzhiyunENDPROC(shmobile_boot_vector_gen2) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun .align 4 75*4882a593Smuzhiyunrwtcsra: 76*4882a593Smuzhiyun .word RWTCSRA_ADDRESS 77*4882a593Smuzhiyunbootrom: 78*4882a593Smuzhiyun .word BOOTROM_ADDRESS 79*4882a593Smuzhiyun .globl shmobile_boot_cpu_gen2 80*4882a593Smuzhiyunshmobile_boot_cpu_gen2: 81*4882a593Smuzhiyun .word 0x00000000 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun .align 2 84*4882a593Smuzhiyun .globl shmobile_boot_fn_gen2 85*4882a593Smuzhiyunshmobile_boot_fn_gen2: 86*4882a593Smuzhiyun .space 4 87*4882a593Smuzhiyun .globl shmobile_boot_size_gen2 88*4882a593Smuzhiyunshmobile_boot_size_gen2: 89*4882a593Smuzhiyun .long . - shmobile_boot_vector_gen2 90*4882a593Smuzhiyun#endif /* CONFIG_ARCH_RCAR_GEN2 */ 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun/* 93*4882a593Smuzhiyun * Per-CPU SMP boot function/argument selection code based on MPIDR 94*4882a593Smuzhiyun */ 95*4882a593Smuzhiyun 96*4882a593SmuzhiyunENTRY(shmobile_smp_boot) 97*4882a593Smuzhiyun mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR 98*4882a593Smuzhiyun and r0, r1, #0xffffff @ MPIDR_HWID_BITMASK 99*4882a593Smuzhiyun @ r0 = cpu_logical_map() value 100*4882a593Smuzhiyun mov r1, #0 @ r1 = CPU index 101*4882a593Smuzhiyun adr r2, 1f 102*4882a593Smuzhiyun ldmia r2, {r5, r6, r7} 103*4882a593Smuzhiyun add r5, r5, r2 @ array of per-cpu mpidr values 104*4882a593Smuzhiyun add r6, r6, r2 @ array of per-cpu functions 105*4882a593Smuzhiyun add r7, r7, r2 @ array of per-cpu arguments 106*4882a593Smuzhiyun 107*4882a593Smuzhiyunshmobile_smp_boot_find_mpidr: 108*4882a593Smuzhiyun ldr r8, [r5, r1, lsl #2] 109*4882a593Smuzhiyun cmp r8, r0 110*4882a593Smuzhiyun bne shmobile_smp_boot_next 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun ldr r9, [r6, r1, lsl #2] 113*4882a593Smuzhiyun cmp r9, #0 114*4882a593Smuzhiyun bne shmobile_smp_boot_found 115*4882a593Smuzhiyun 116*4882a593Smuzhiyunshmobile_smp_boot_next: 117*4882a593Smuzhiyun add r1, r1, #1 118*4882a593Smuzhiyun cmp r1, #NR_CPUS 119*4882a593Smuzhiyun blo shmobile_smp_boot_find_mpidr 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun b shmobile_smp_sleep 122*4882a593Smuzhiyun 123*4882a593Smuzhiyunshmobile_smp_boot_found: 124*4882a593Smuzhiyun ldr r0, [r7, r1, lsl #2] 125*4882a593Smuzhiyun ret r9 126*4882a593SmuzhiyunENDPROC(shmobile_smp_boot) 127*4882a593Smuzhiyun 128*4882a593SmuzhiyunENTRY(shmobile_smp_sleep) 129*4882a593Smuzhiyun wfi 130*4882a593Smuzhiyun b shmobile_smp_boot 131*4882a593SmuzhiyunENDPROC(shmobile_smp_sleep) 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun .align 2 134*4882a593Smuzhiyun1: .long shmobile_smp_mpidr - . 135*4882a593Smuzhiyun .long shmobile_smp_fn - 1b 136*4882a593Smuzhiyun .long shmobile_smp_arg - 1b 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun .bss 139*4882a593Smuzhiyun .globl shmobile_smp_mpidr 140*4882a593Smuzhiyunshmobile_smp_mpidr: 141*4882a593Smuzhiyun .space NR_CPUS * 4 142*4882a593Smuzhiyun .globl shmobile_smp_fn 143*4882a593Smuzhiyunshmobile_smp_fn: 144*4882a593Smuzhiyun .space NR_CPUS * 4 145*4882a593Smuzhiyun .globl shmobile_smp_arg 146*4882a593Smuzhiyunshmobile_smp_arg: 147*4882a593Smuzhiyun .space NR_CPUS * 4 148