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

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

DEFINITIONS

This source file includes following definitions.
  1. spear_write_pen_release
  2. spear13xx_secondary_init
  3. spear13xx_boot_secondary
  4. spear13xx_smp_init_cpus
  5. spear13xx_smp_prepare_cpus

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * arch/arm/mach-spear13xx/platsmp.c
   4  *
   5  * based upon linux/arch/arm/mach-realview/platsmp.c
   6  *
   7  * Copyright (C) 2012 ST Microelectronics Ltd.
   8  * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
   9  */
  10 
  11 #include <linux/delay.h>
  12 #include <linux/jiffies.h>
  13 #include <linux/io.h>
  14 #include <linux/smp.h>
  15 #include <asm/cacheflush.h>
  16 #include <asm/smp_scu.h>
  17 #include <mach/spear.h>
  18 #include "generic.h"
  19 
  20 /* XXX spear_pen_release is cargo culted code - DO NOT COPY XXX */
  21 volatile int spear_pen_release = -1;
  22 
  23 /*
  24  * XXX CARGO CULTED CODE - DO NOT COPY XXX
  25  *
  26  * Write spear_pen_release in a way that is guaranteed to be visible to
  27  * all observers, irrespective of whether they're taking part in coherency
  28  * or not.  This is necessary for the hotplug code to work reliably.
  29  */
  30 static void spear_write_pen_release(int val)
  31 {
  32         spear_pen_release = val;
  33         smp_wmb();
  34         sync_cache_w(&spear_pen_release);
  35 }
  36 
  37 static DEFINE_SPINLOCK(boot_lock);
  38 
  39 static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
  40 
  41 static void spear13xx_secondary_init(unsigned int cpu)
  42 {
  43         /*
  44          * let the primary processor know we're out of the
  45          * pen, then head off into the C entry point
  46          */
  47         spear_write_pen_release(-1);
  48 
  49         /*
  50          * Synchronise with the boot thread.
  51          */
  52         spin_lock(&boot_lock);
  53         spin_unlock(&boot_lock);
  54 }
  55 
  56 static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
  57 {
  58         unsigned long timeout;
  59 
  60         /*
  61          * set synchronisation state between this boot processor
  62          * and the secondary one
  63          */
  64         spin_lock(&boot_lock);
  65 
  66         /*
  67          * The secondary processor is waiting to be released from
  68          * the holding pen - release it, then wait for it to flag
  69          * that it has been released by resetting spear_pen_release.
  70          *
  71          * Note that "spear_pen_release" is the hardware CPU ID, whereas
  72          * "cpu" is Linux's internal ID.
  73          */
  74         spear_write_pen_release(cpu);
  75 
  76         timeout = jiffies + (1 * HZ);
  77         while (time_before(jiffies, timeout)) {
  78                 smp_rmb();
  79                 if (spear_pen_release == -1)
  80                         break;
  81 
  82                 udelay(10);
  83         }
  84 
  85         /*
  86          * now the secondary core is starting up let it run its
  87          * calibrations, then wait for it to finish
  88          */
  89         spin_unlock(&boot_lock);
  90 
  91         return spear_pen_release != -1 ? -ENOSYS : 0;
  92 }
  93 
  94 /*
  95  * Initialise the CPU possible map early - this describes the CPUs
  96  * which may be present or become present in the system.
  97  */
  98 static void __init spear13xx_smp_init_cpus(void)
  99 {
 100         unsigned int i, ncores = scu_get_core_count(scu_base);
 101 
 102         if (ncores > nr_cpu_ids) {
 103                 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
 104                         ncores, nr_cpu_ids);
 105                 ncores = nr_cpu_ids;
 106         }
 107 
 108         for (i = 0; i < ncores; i++)
 109                 set_cpu_possible(i, true);
 110 }
 111 
 112 static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
 113 {
 114 
 115         scu_enable(scu_base);
 116 
 117         /*
 118          * Write the address of secondary startup into the system-wide location
 119          * (presently it is in SRAM). The BootMonitor waits until it receives a
 120          * soft interrupt, and then the secondary CPU branches to this address.
 121          */
 122         __raw_writel(__pa_symbol(spear13xx_secondary_startup), SYS_LOCATION);
 123 }
 124 
 125 const struct smp_operations spear13xx_smp_ops __initconst = {
 126        .smp_init_cpus           = spear13xx_smp_init_cpus,
 127        .smp_prepare_cpus        = spear13xx_smp_prepare_cpus,
 128        .smp_secondary_init      = spear13xx_secondary_init,
 129        .smp_boot_secondary      = spear13xx_boot_secondary,
 130 #ifdef CONFIG_HOTPLUG_CPU
 131        .cpu_die                 = spear13xx_cpu_die,
 132 #endif
 133 };

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