root/arch/sh/kernel/cpu/sh2/smp-j2.c

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

DEFINITIONS

This source file includes following definitions.
  1. j2_ipi_interrupt_handler
  2. j2_smp_setup
  3. j2_prepare_cpus
  4. j2_start_cpu
  5. j2_smp_processor_id
  6. j2_send_ipi

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * SMP support for J2 processor
   4  *
   5  * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
   6  */
   7 
   8 #include <linux/smp.h>
   9 #include <linux/interrupt.h>
  10 #include <linux/io.h>
  11 #include <linux/of_address.h>
  12 #include <linux/of_irq.h>
  13 #include <asm/cmpxchg.h>
  14 
  15 DEFINE_PER_CPU(unsigned, j2_ipi_messages);
  16 
  17 extern u32 *sh2_cpuid_addr;
  18 static u32 *j2_ipi_trigger;
  19 static int j2_ipi_irq;
  20 
  21 static irqreturn_t j2_ipi_interrupt_handler(int irq, void *arg)
  22 {
  23         unsigned cpu = hard_smp_processor_id();
  24         volatile unsigned *pmsg = &per_cpu(j2_ipi_messages, cpu);
  25         unsigned messages, i;
  26 
  27         do messages = *pmsg;
  28         while (cmpxchg(pmsg, messages, 0) != messages);
  29 
  30         if (!messages) return IRQ_NONE;
  31 
  32         for (i=0; i<SMP_MSG_NR; i++)
  33                 if (messages & (1U<<i))
  34                         smp_message_recv(i);
  35 
  36         return IRQ_HANDLED;
  37 }
  38 
  39 static void j2_smp_setup(void)
  40 {
  41 }
  42 
  43 static void j2_prepare_cpus(unsigned int max_cpus)
  44 {
  45         struct device_node *np;
  46         unsigned i, max = 1;
  47 
  48         np = of_find_compatible_node(NULL, NULL, "jcore,ipi-controller");
  49         if (!np)
  50                 goto out;
  51 
  52         j2_ipi_irq = irq_of_parse_and_map(np, 0);
  53         j2_ipi_trigger = of_iomap(np, 0);
  54         if (!j2_ipi_irq || !j2_ipi_trigger)
  55                 goto out;
  56 
  57         np = of_find_compatible_node(NULL, NULL, "jcore,cpuid-mmio");
  58         if (!np)
  59                 goto out;
  60 
  61         sh2_cpuid_addr = of_iomap(np, 0);
  62         if (!sh2_cpuid_addr)
  63                 goto out;
  64 
  65         if (request_irq(j2_ipi_irq, j2_ipi_interrupt_handler, IRQF_PERCPU,
  66                         "ipi", (void *)j2_ipi_interrupt_handler) != 0)
  67                 goto out;
  68 
  69         max = max_cpus;
  70 out:
  71         /* Disable any cpus past max_cpus, or all secondaries if we didn't
  72          * get the necessary resources to support SMP. */
  73         for (i=max; i<NR_CPUS; i++) {
  74                 set_cpu_possible(i, false);
  75                 set_cpu_present(i, false);
  76         }
  77 }
  78 
  79 static void j2_start_cpu(unsigned int cpu, unsigned long entry_point)
  80 {
  81         struct device_node *np;
  82         u32 regs[2];
  83         void __iomem *release, *initpc;
  84 
  85         if (!cpu) return;
  86 
  87         np = of_get_cpu_node(cpu, NULL);
  88         if (!np) return;
  89 
  90         if (of_property_read_u32_array(np, "cpu-release-addr", regs, 2)) return;
  91         release = ioremap_nocache(regs[0], sizeof(u32));
  92         initpc = ioremap_nocache(regs[1], sizeof(u32));
  93 
  94         __raw_writel(entry_point, initpc);
  95         __raw_writel(1, release);
  96 
  97         iounmap(initpc);
  98         iounmap(release);
  99 
 100         pr_info("J2 SMP: requested start of cpu %u\n", cpu);
 101 }
 102 
 103 static unsigned int j2_smp_processor_id(void)
 104 {
 105         return __raw_readl(sh2_cpuid_addr);
 106 }
 107 
 108 static void j2_send_ipi(unsigned int cpu, unsigned int message)
 109 {
 110         volatile unsigned *pmsg;
 111         unsigned old;
 112         unsigned long val;
 113 
 114         /* There is only one IPI interrupt shared by all messages, so
 115          * we keep a separate interrupt flag per message type in sw. */
 116         pmsg = &per_cpu(j2_ipi_messages, cpu);
 117         do old = *pmsg;
 118         while (cmpxchg(pmsg, old, old|(1U<<message)) != old);
 119 
 120         /* Generate the actual interrupt by writing to CCRn bit 28. */
 121         val = __raw_readl(j2_ipi_trigger + cpu);
 122         __raw_writel(val | (1U<<28), j2_ipi_trigger + cpu);
 123 }
 124 
 125 static struct plat_smp_ops j2_smp_ops = {
 126         .smp_setup              = j2_smp_setup,
 127         .prepare_cpus           = j2_prepare_cpus,
 128         .start_cpu              = j2_start_cpu,
 129         .smp_processor_id       = j2_smp_processor_id,
 130         .send_ipi               = j2_send_ipi,
 131         .cpu_die                = native_cpu_die,
 132         .cpu_disable            = native_cpu_disable,
 133         .play_dead              = native_play_dead,
 134 };
 135 
 136 CPU_METHOD_OF_DECLARE(j2_cpu_method, "jcore,spin-table", &j2_smp_ops);

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