root/arch/arm/mach-zx/platsmp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zx_smp_prepare_cpus
  2. zx_boot_secondary
  3. cpu_enter_lowpower
  4. zx_cpu_kill
  5. zx_cpu_die
  6. zx_secondary_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2014 Linaro Ltd.
   4  * Copyright (C) 2014 ZTE Corporation.
   5  */
   6 
   7 #include <linux/delay.h>
   8 #include <linux/errno.h>
   9 #include <linux/init.h>
  10 #include <linux/io.h>
  11 #include <linux/jiffies.h>
  12 #include <linux/of.h>
  13 #include <linux/of_address.h>
  14 #include <linux/smp.h>
  15 
  16 #include <asm/cacheflush.h>
  17 #include <asm/cp15.h>
  18 #include <asm/fncpy.h>
  19 #include <asm/proc-fns.h>
  20 #include <asm/smp_scu.h>
  21 #include <asm/smp_plat.h>
  22 
  23 #include "core.h"
  24 
  25 #define AON_SYS_CTRL_RESERVED1          0xa8
  26 
  27 #define BUS_MATRIX_REMAP_CONFIG         0x00
  28 
  29 #define PCU_CPU0_CTRL                   0x00
  30 #define PCU_CPU1_CTRL                   0x04
  31 #define PCU_CPU1_ST                     0x0c
  32 #define PCU_GLOBAL_CTRL                 0x14
  33 #define PCU_EXPEND_CONTROL              0x34
  34 
  35 #define ZX_IRAM_BASE                    0x00200000
  36 
  37 static void __iomem *pcu_base;
  38 static void __iomem *matrix_base;
  39 static void __iomem *scu_base;
  40 
  41 void __init zx_smp_prepare_cpus(unsigned int max_cpus)
  42 {
  43         struct device_node *np;
  44         unsigned long base = 0;
  45         void __iomem *aonsysctrl_base;
  46         void __iomem *sys_iram;
  47 
  48         base = scu_a9_get_base();
  49         scu_base = ioremap(base, SZ_256);
  50         if (!scu_base) {
  51                 pr_err("%s: failed to map scu\n", __func__);
  52                 return;
  53         }
  54 
  55         scu_enable(scu_base);
  56 
  57         np = of_find_compatible_node(NULL, NULL, "zte,sysctrl");
  58         if (!np) {
  59                 pr_err("%s: failed to find sysctrl node\n", __func__);
  60                 return;
  61         }
  62 
  63         aonsysctrl_base = of_iomap(np, 0);
  64         if (!aonsysctrl_base) {
  65                 pr_err("%s: failed to map aonsysctrl\n", __func__);
  66                 of_node_put(np);
  67                 return;
  68         }
  69 
  70         /*
  71          * Write the address of secondary startup into the
  72          * system-wide flags register. The BootMonitor waits
  73          * until it receives a soft interrupt, and then the
  74          * secondary CPU branches to this address.
  75          */
  76         __raw_writel(__pa_symbol(zx_secondary_startup),
  77                      aonsysctrl_base + AON_SYS_CTRL_RESERVED1);
  78 
  79         iounmap(aonsysctrl_base);
  80         of_node_put(np);
  81 
  82         np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
  83         pcu_base = of_iomap(np, 0);
  84         of_node_put(np);
  85         WARN_ON(!pcu_base);
  86 
  87         np = of_find_compatible_node(NULL, NULL, "zte,zx-bus-matrix");
  88         matrix_base = of_iomap(np, 0);
  89         of_node_put(np);
  90         WARN_ON(!matrix_base);
  91 
  92         /* Map the first 4 KB IRAM for suspend usage */
  93         sys_iram = __arm_ioremap_exec(ZX_IRAM_BASE, PAGE_SIZE, false);
  94         zx_secondary_startup_pa = __pa_symbol(zx_secondary_startup);
  95         fncpy(sys_iram, &zx_resume_jump, zx_suspend_iram_sz);
  96 }
  97 
  98 static int zx_boot_secondary(unsigned int cpu, struct task_struct *idle)
  99 {
 100         static bool first_boot = true;
 101 
 102         if (first_boot) {
 103                 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 104                 first_boot = false;
 105                 return 0;
 106         }
 107 
 108         /* Swap the base address mapping between IRAM and IROM */
 109         writel_relaxed(0x1, matrix_base + BUS_MATRIX_REMAP_CONFIG);
 110 
 111         /* Power on CPU1 */
 112         writel_relaxed(0x0, pcu_base + PCU_CPU1_CTRL);
 113 
 114         /* Wait for power on ack */
 115         while (readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x4)
 116                 cpu_relax();
 117 
 118         /* Swap back the mapping of IRAM and IROM */
 119         writel_relaxed(0x0, matrix_base + BUS_MATRIX_REMAP_CONFIG);
 120 
 121         return 0;
 122 }
 123 
 124 #ifdef CONFIG_HOTPLUG_CPU
 125 static inline void cpu_enter_lowpower(void)
 126 {
 127         unsigned int v;
 128 
 129         asm volatile(
 130                 "mcr    p15, 0, %1, c7, c5, 0\n"
 131         "       mcr     p15, 0, %1, c7, c10, 4\n"
 132         /*
 133          * Turn off coherency
 134          */
 135         "       mrc     p15, 0, %0, c1, c0, 1\n"
 136         "       bic     %0, %0, %3\n"
 137         "       mcr     p15, 0, %0, c1, c0, 1\n"
 138         "       mrc     p15, 0, %0, c1, c0, 0\n"
 139         "       bic     %0, %0, %2\n"
 140         "       mcr     p15, 0, %0, c1, c0, 0\n"
 141           : "=&r" (v)
 142           : "r" (0), "Ir" (CR_C), "Ir" (0x40)
 143           : "cc");
 144 }
 145 
 146 static int zx_cpu_kill(unsigned int cpu)
 147 {
 148         unsigned long timeout = jiffies + msecs_to_jiffies(2000);
 149 
 150         writel_relaxed(0x2, pcu_base + PCU_CPU1_CTRL);
 151 
 152         while ((readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x3) != 0x0) {
 153                 if (time_after(jiffies, timeout)) {
 154                         pr_err("*** cpu1 poweroff timeout\n");
 155                         break;
 156                 }
 157         }
 158         return 1;
 159 }
 160 
 161 static void zx_cpu_die(unsigned int cpu)
 162 {
 163         scu_power_mode(scu_base, SCU_PM_POWEROFF);
 164         cpu_enter_lowpower();
 165 
 166         while (1)
 167                 cpu_do_idle();
 168 }
 169 #endif
 170 
 171 static void zx_secondary_init(unsigned int cpu)
 172 {
 173         scu_power_mode(scu_base, SCU_PM_NORMAL);
 174 }
 175 
 176 static const struct smp_operations zx_smp_ops __initconst = {
 177         .smp_prepare_cpus       = zx_smp_prepare_cpus,
 178         .smp_secondary_init     = zx_secondary_init,
 179         .smp_boot_secondary     = zx_boot_secondary,
 180 #ifdef CONFIG_HOTPLUG_CPU
 181         .cpu_kill               = zx_cpu_kill,
 182         .cpu_die                = zx_cpu_die,
 183 #endif
 184 };
 185 
 186 CPU_METHOD_OF_DECLARE(zx_smp, "zte,zx296702-smp", &zx_smp_ops);

/* [<][>][^][v][top][bottom][index][help] */