Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
0004  *
0005  * Copyright (C) 2010  Magnus Damm
0006  * Copyright (C) 2010  Takashi Yoshii
0007  */
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/smp.h>
0011 #include <linux/io.h>
0012 #include <linux/delay.h>
0013 
0014 #include <asm/smp_plat.h>
0015 
0016 #include "common.h"
0017 #include "sh73a0.h"
0018 
0019 #define CPG_BASE2   0xe6151000
0020 #define WUPCR       0x10    /* System-CPU Wake Up Control Register */
0021 #define SRESCR      0x18    /* System-CPU Software Reset Control Register */
0022 #define PSTR        0x40    /* System-CPU Power Status Register */
0023 
0024 #define SYSC_BASE   0xe6180000
0025 #define SBAR        0x20    /* SYS Boot Address Register */
0026 
0027 #define AP_BASE     0xe6f10000
0028 #define APARMBAREA  0x20    /* Address Translation Area Register */
0029 
0030 #define SH73A0_SCU_BASE 0xf0000000
0031 
0032 static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
0033 {
0034     unsigned int lcpu = cpu_logical_map(cpu);
0035     void __iomem *cpg2 = ioremap(CPG_BASE2, PAGE_SIZE);
0036 
0037     if (((readl(cpg2 + PSTR) >> (4 * lcpu)) & 3) == 3)
0038         writel(1 << lcpu, cpg2 + WUPCR);    /* wake up */
0039     else
0040         writel(1 << lcpu, cpg2 + SRESCR);   /* reset */
0041     iounmap(cpg2);
0042     return 0;
0043 }
0044 
0045 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
0046 {
0047     void __iomem *ap = ioremap(AP_BASE, PAGE_SIZE);
0048     void __iomem *sysc = ioremap(SYSC_BASE, PAGE_SIZE);
0049 
0050     /* Map the reset vector (in headsmp.S) */
0051     writel(0, ap + APARMBAREA);      /* 4k */
0052     writel(__pa(shmobile_boot_vector), sysc + SBAR);
0053     iounmap(sysc);
0054     iounmap(ap);
0055 
0056     /* setup sh73a0 specific SCU bits */
0057     shmobile_smp_scu_prepare_cpus(SH73A0_SCU_BASE, max_cpus);
0058 }
0059 
0060 const struct smp_operations sh73a0_smp_ops __initconst = {
0061     .smp_prepare_cpus   = sh73a0_smp_prepare_cpus,
0062     .smp_boot_secondary = sh73a0_boot_secondary,
0063 #ifdef CONFIG_HOTPLUG_CPU
0064     .cpu_can_disable    = shmobile_smp_cpu_can_disable,
0065     .cpu_die        = shmobile_smp_scu_cpu_die,
0066     .cpu_kill       = shmobile_smp_scu_cpu_kill,
0067 #endif
0068 };