2 * Copyright(c) 2015 EZchip Technologies.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * The full GNU General Public License is included in this distribution in
14 * the file called "COPYING".
17 #include <linux/smp.h>
18 #include <linux/of_fdt.h>
20 #include <linux/irqdomain.h>
22 #include <plat/ctop.h>
26 #define NPS_DEFAULT_MSID 0x34
27 #define NPS_MTM_CPU_CFG 0x90
29 static char smp_cpuinfo_buf
[128] = {"Extn [EZNPS-SMP]\t: On\n"};
31 /* Get cpu map from device tree */
32 static int __init
eznps_get_map(const char *name
, struct cpumask
*cpumask
)
34 unsigned long dt_root
= of_get_flat_dt_root();
37 buf
= of_get_flat_dt_prop(dt_root
, name
, NULL
);
41 cpulist_parse(buf
, cpumask
);
46 /* Update board cpu maps */
47 static void __init
eznps_init_cpumasks(void)
49 struct cpumask cpumask
;
51 if (eznps_get_map("present-cpus", &cpumask
)) {
52 pr_err("Failed to get present-cpus from dtb");
55 init_cpu_present(&cpumask
);
57 if (eznps_get_map("possible-cpus", &cpumask
)) {
58 pr_err("Failed to get possible-cpus from dtb");
61 init_cpu_possible(&cpumask
);
64 static void eznps_init_core(unsigned int cpu
)
67 struct nps_host_reg_aux_hw_comply hw_comply
;
68 struct nps_host_reg_aux_lpc lpc
;
70 if (NPS_CPU_TO_THREAD_NUM(cpu
) != 0)
73 hw_comply
.value
= read_aux_reg(CTOP_AUX_HW_COMPLY
);
77 write_aux_reg(CTOP_AUX_HW_COMPLY
, hw_comply
.value
);
79 /* Enable MMU clock */
81 write_aux_reg(CTOP_AUX_LPC
, lpc
.value
);
85 /* Write to general purpose register in CRG */
86 sync_value
= ioread32be(REG_GEN_PURP_0
);
87 sync_value
|= NPS_CRG_SYNC_BIT
;
88 iowrite32be(sync_value
, REG_GEN_PURP_0
);
93 * Master kick starting another CPU
95 static void __init
eznps_smp_wakeup_cpu(int cpu
, unsigned long pc
)
97 struct nps_host_reg_mtm_cpu_cfg cpu_cfg
;
99 if (mtm_enable_thread(cpu
) == 0)
102 /* set PC, dmsid, and start CPU */
103 cpu_cfg
.value
= (u32
)res_service
;
104 cpu_cfg
.dmsid
= NPS_DEFAULT_MSID
;
106 iowrite32be(cpu_cfg
.value
, nps_mtm_reg_addr(cpu
, NPS_MTM_CPU_CFG
));
109 static void eznps_ipi_send(int cpu
)
111 struct global_id gid
;
115 u32 num
:8, cluster
:8, core
:8, thread
:8;
122 ipi
.thread
= get_thread(gid
);
124 ipi
.cluster
= nps_cluster_logic_to_phys(gid
.cluster
);
125 ipi
.num
= NPS_IPI_IRQ
;
127 __asm__
__volatile__(
131 : "r"(ipi
.value
), "i"(CTOP_INST_ASRI_0_R3
)
135 static void eznps_init_per_cpu(int cpu
)
137 smp_ipi_irq_setup(cpu
, NPS_IPI_IRQ
);
139 eznps_init_core(cpu
);
140 mtm_enable_core(cpu
);
143 struct plat_smp_ops plat_smp_ops
= {
144 .info
= smp_cpuinfo_buf
,
145 .init_early_smp
= eznps_init_cpumasks
,
146 .cpu_kick
= eznps_smp_wakeup_cpu
,
147 .ipi_send
= eznps_ipi_send
,
148 .init_per_cpu
= eznps_init_per_cpu
,