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

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

DEFINITIONS

This source file includes following definitions.
  1. socfpga_boot_secondary
  2. socfpga_a10_boot_secondary
  3. socfpga_smp_prepare_cpus
  4. socfpga_cpu_die
  5. socfpga_cpu_kill

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2010-2011 Calxeda, Inc.
   4  * Copyright 2012 Pavel Machek <pavel@denx.de>
   5  * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
   6  * Copyright (C) 2012 Altera Corporation
   7  */
   8 #include <linux/delay.h>
   9 #include <linux/init.h>
  10 #include <linux/smp.h>
  11 #include <linux/io.h>
  12 #include <linux/of.h>
  13 #include <linux/of_address.h>
  14 
  15 #include <asm/cacheflush.h>
  16 #include <asm/smp_scu.h>
  17 #include <asm/smp_plat.h>
  18 
  19 #include "core.h"
  20 
  21 static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
  22 {
  23         int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
  24 
  25         if (socfpga_cpu1start_addr) {
  26                 /* This will put CPU #1 into reset. */
  27                 writel(RSTMGR_MPUMODRST_CPU1,
  28                        rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
  29 
  30                 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
  31 
  32                 writel(__pa_symbol(secondary_startup),
  33                        sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff));
  34 
  35                 flush_cache_all();
  36                 smp_wmb();
  37                 outer_clean_range(0, trampoline_size);
  38 
  39                 /* This will release CPU #1 out of reset. */
  40                 writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
  41         }
  42 
  43         return 0;
  44 }
  45 
  46 static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle)
  47 {
  48         int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
  49 
  50         if (socfpga_cpu1start_addr) {
  51                 writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr +
  52                        SOCFPGA_A10_RSTMGR_MODMPURST);
  53                 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
  54 
  55                 writel(__pa_symbol(secondary_startup),
  56                        sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff));
  57 
  58                 flush_cache_all();
  59                 smp_wmb();
  60                 outer_clean_range(0, trampoline_size);
  61 
  62                 /* This will release CPU #1 out of reset. */
  63                 writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST);
  64         }
  65 
  66         return 0;
  67 }
  68 
  69 static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
  70 {
  71         struct device_node *np;
  72         void __iomem *socfpga_scu_base_addr;
  73 
  74         np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
  75         if (!np) {
  76                 pr_err("%s: missing scu\n", __func__);
  77                 return;
  78         }
  79 
  80         socfpga_scu_base_addr = of_iomap(np, 0);
  81         if (!socfpga_scu_base_addr)
  82                 return;
  83         scu_enable(socfpga_scu_base_addr);
  84 }
  85 
  86 #ifdef CONFIG_HOTPLUG_CPU
  87 /*
  88  * platform-specific code to shutdown a CPU
  89  *
  90  * Called with IRQs disabled
  91  */
  92 static void socfpga_cpu_die(unsigned int cpu)
  93 {
  94         /* Do WFI. If we wake up early, go back into WFI */
  95         while (1)
  96                 cpu_do_idle();
  97 }
  98 
  99 /*
 100  * We need a dummy function so that platform_can_cpu_hotplug() knows
 101  * we support CPU hotplug. However, the function does not need to do
 102  * anything, because CPUs going offline just do WFI. We could reset
 103  * the CPUs but it would increase power consumption.
 104  */
 105 static int socfpga_cpu_kill(unsigned int cpu)
 106 {
 107         return 1;
 108 }
 109 #endif
 110 
 111 static const struct smp_operations socfpga_smp_ops __initconst = {
 112         .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
 113         .smp_boot_secondary     = socfpga_boot_secondary,
 114 #ifdef CONFIG_HOTPLUG_CPU
 115         .cpu_die                = socfpga_cpu_die,
 116         .cpu_kill               = socfpga_cpu_kill,
 117 #endif
 118 };
 119 
 120 static const struct smp_operations socfpga_a10_smp_ops __initconst = {
 121         .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
 122         .smp_boot_secondary     = socfpga_a10_boot_secondary,
 123 #ifdef CONFIG_HOTPLUG_CPU
 124         .cpu_die                = socfpga_cpu_die,
 125         .cpu_kill               = socfpga_cpu_kill,
 126 #endif
 127 };
 128 
 129 CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops);
 130 CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops);

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