Merge tag 'mips_fixes_5.2_2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips...
[linux-2.6/linux-2.6-arm.git] / arch / arc / plat-eznps / smp.c
blobf119cb7de2ae3751c5610068e8a80240479ee8c5
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright(c) 2015 EZchip Technologies.
4 */
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>
15 #define NPS_DEFAULT_MSID 0x34
16 #define NPS_MTM_CPU_CFG 0x90
18 static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
20 /* Get cpu map from device tree */
21 static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
23 unsigned long dt_root = of_get_flat_dt_root();
24 const char *buf;
26 buf = of_get_flat_dt_prop(dt_root, name, NULL);
27 if (!buf)
28 return 1;
30 cpulist_parse(buf, cpumask);
32 return 0;
35 /* Update board cpu maps */
36 static void __init eznps_init_cpumasks(void)
38 struct cpumask cpumask;
40 if (eznps_get_map("present-cpus", &cpumask)) {
41 pr_err("Failed to get present-cpus from dtb");
42 return;
44 init_cpu_present(&cpumask);
46 if (eznps_get_map("possible-cpus", &cpumask)) {
47 pr_err("Failed to get possible-cpus from dtb");
48 return;
50 init_cpu_possible(&cpumask);
53 static void eznps_init_core(unsigned int cpu)
55 u32 sync_value;
56 struct nps_host_reg_aux_hw_comply hw_comply;
57 struct nps_host_reg_aux_lpc lpc;
59 if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
60 return;
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);
68 /* Enable MMU clock */
69 lpc.mep = 1;
70 write_aux_reg(CTOP_AUX_LPC, lpc.value);
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);
82 * Master kick starting another CPU
84 static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
86 struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
88 if (mtm_enable_thread(cpu) == 0)
89 return;
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));
98 static void eznps_ipi_send(int cpu)
100 struct global_id gid;
101 struct {
102 union {
103 struct {
104 u32 num:8, cluster:8, core:8, thread:8;
106 u32 value;
108 } ipi;
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;
116 __asm__ __volatile__(
117 " mov r3, %0\n"
118 " .word %1\n"
120 : "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
121 : "r3");
124 static void eznps_init_per_cpu(int cpu)
126 smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
128 eznps_init_core(cpu);
129 mtm_enable_core(cpu);
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,