root/arch/arc/plat-eznps/smp.c

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

DEFINITIONS

This source file includes following definitions.
  1. eznps_get_map
  2. eznps_init_cpumasks
  3. eznps_init_core
  4. eznps_smp_wakeup_cpu
  5. eznps_ipi_send
  6. eznps_init_per_cpu

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright(c) 2015 EZchip Technologies.
   4  */
   5 
   6 #include <linux/smp.h>
   7 #include <linux/of_fdt.h>
   8 #include <linux/io.h>
   9 #include <linux/irqdomain.h>
  10 #include <asm/irq.h>
  11 #include <plat/ctop.h>
  12 #include <plat/smp.h>
  13 #include <plat/mtm.h>
  14 
  15 #define NPS_DEFAULT_MSID        0x34
  16 #define NPS_MTM_CPU_CFG         0x90
  17 
  18 static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
  19 
  20 /* Get cpu map from device tree */
  21 static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
  22 {
  23         unsigned long dt_root = of_get_flat_dt_root();
  24         const char *buf;
  25 
  26         buf = of_get_flat_dt_prop(dt_root, name, NULL);
  27         if (!buf)
  28                 return 1;
  29 
  30         cpulist_parse(buf, cpumask);
  31 
  32         return 0;
  33 }
  34 
  35 /* Update board cpu maps */
  36 static void __init eznps_init_cpumasks(void)
  37 {
  38         struct cpumask cpumask;
  39 
  40         if (eznps_get_map("present-cpus", &cpumask)) {
  41                 pr_err("Failed to get present-cpus from dtb");
  42                 return;
  43         }
  44         init_cpu_present(&cpumask);
  45 
  46         if (eznps_get_map("possible-cpus", &cpumask)) {
  47                 pr_err("Failed to get possible-cpus from dtb");
  48                 return;
  49         }
  50         init_cpu_possible(&cpumask);
  51 }
  52 
  53 static void eznps_init_core(unsigned int cpu)
  54 {
  55         u32 sync_value;
  56         struct nps_host_reg_aux_hw_comply hw_comply;
  57         struct nps_host_reg_aux_lpc lpc;
  58 
  59         if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
  60                 return;
  61 
  62         hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
  63         hw_comply.me  = 1;
  64         hw_comply.le  = 1;
  65         hw_comply.te  = 1;
  66         write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
  67 
  68         /* Enable MMU clock */
  69         lpc.mep = 1;
  70         write_aux_reg(CTOP_AUX_LPC, lpc.value);
  71 
  72         /* Boot CPU only */
  73         if (!cpu) {
  74                 /* Write to general purpose register in CRG */
  75                 sync_value = ioread32be(REG_GEN_PURP_0);
  76                 sync_value |= NPS_CRG_SYNC_BIT;
  77                 iowrite32be(sync_value, REG_GEN_PURP_0);
  78         }
  79 }
  80 
  81 /*
  82  * Master kick starting another CPU
  83  */
  84 static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
  85 {
  86         struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
  87 
  88         if (mtm_enable_thread(cpu) == 0)
  89                 return;
  90 
  91         /* set PC, dmsid, and start CPU */
  92         cpu_cfg.value = (u32)res_service;
  93         cpu_cfg.dmsid = NPS_DEFAULT_MSID;
  94         cpu_cfg.cs = 1;
  95         iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
  96 }
  97 
  98 static void eznps_ipi_send(int cpu)
  99 {
 100         struct global_id gid;
 101         struct {
 102                 union {
 103                         struct {
 104                                 u32 num:8, cluster:8, core:8, thread:8;
 105                         };
 106                         u32 value;
 107                 };
 108         } ipi;
 109 
 110         gid.value = cpu;
 111         ipi.thread = get_thread(gid);
 112         ipi.core = gid.core;
 113         ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
 114         ipi.num = NPS_IPI_IRQ;
 115 
 116         __asm__ __volatile__(
 117         "       mov r3, %0\n"
 118         "       .word %1\n"
 119         :
 120         : "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
 121         : "r3");
 122 }
 123 
 124 static void eznps_init_per_cpu(int cpu)
 125 {
 126         smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
 127 
 128         eznps_init_core(cpu);
 129         mtm_enable_core(cpu);
 130 }
 131 
 132 struct plat_smp_ops plat_smp_ops = {
 133         .info           = smp_cpuinfo_buf,
 134         .init_early_smp = eznps_init_cpumasks,
 135         .cpu_kick       = eznps_smp_wakeup_cpu,
 136         .ipi_send       = eznps_ipi_send,
 137         .init_per_cpu   = eznps_init_per_cpu,
 138 };

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