123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /*
- * Copyright(c) 2015 EZchip Technologies.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- */
- #include <linux/smp.h>
- #include <linux/of_fdt.h>
- #include <linux/io.h>
- #include <linux/irqdomain.h>
- #include <asm/irq.h>
- #include <plat/ctop.h>
- #include <plat/smp.h>
- #include <plat/mtm.h>
- #define NPS_DEFAULT_MSID 0x34
- #define NPS_MTM_CPU_CFG 0x90
- static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
- /* Get cpu map from device tree */
- static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
- {
- unsigned long dt_root = of_get_flat_dt_root();
- const char *buf;
- buf = of_get_flat_dt_prop(dt_root, name, NULL);
- if (!buf)
- return 1;
- cpulist_parse(buf, cpumask);
- return 0;
- }
- /* Update board cpu maps */
- static void __init eznps_init_cpumasks(void)
- {
- struct cpumask cpumask;
- if (eznps_get_map("present-cpus", &cpumask)) {
- pr_err("Failed to get present-cpus from dtb");
- return;
- }
- init_cpu_present(&cpumask);
- if (eznps_get_map("possible-cpus", &cpumask)) {
- pr_err("Failed to get possible-cpus from dtb");
- return;
- }
- init_cpu_possible(&cpumask);
- }
- static void eznps_init_core(unsigned int cpu)
- {
- u32 sync_value;
- struct nps_host_reg_aux_hw_comply hw_comply;
- struct nps_host_reg_aux_lpc lpc;
- if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
- return;
- hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
- hw_comply.me = 1;
- hw_comply.le = 1;
- hw_comply.te = 1;
- write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
- /* Enable MMU clock */
- lpc.mep = 1;
- write_aux_reg(CTOP_AUX_LPC, lpc.value);
- /* Boot CPU only */
- if (!cpu) {
- /* Write to general purpose register in CRG */
- sync_value = ioread32be(REG_GEN_PURP_0);
- sync_value |= NPS_CRG_SYNC_BIT;
- iowrite32be(sync_value, REG_GEN_PURP_0);
- }
- }
- /*
- * Master kick starting another CPU
- */
- static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
- {
- struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
- if (mtm_enable_thread(cpu) == 0)
- return;
- /* set PC, dmsid, and start CPU */
- cpu_cfg.value = (u32)res_service;
- cpu_cfg.dmsid = NPS_DEFAULT_MSID;
- cpu_cfg.cs = 1;
- iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
- }
- static void eznps_ipi_send(int cpu)
- {
- struct global_id gid;
- struct {
- union {
- struct {
- u32 num:8, cluster:8, core:8, thread:8;
- };
- u32 value;
- };
- } ipi;
- gid.value = cpu;
- ipi.thread = get_thread(gid);
- ipi.core = gid.core;
- ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
- ipi.num = NPS_IPI_IRQ;
- __asm__ __volatile__(
- " mov r3, %0\n"
- " .word %1\n"
- :
- : "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
- : "r3");
- }
- static void eznps_init_per_cpu(int cpu)
- {
- smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
- eznps_init_core(cpu);
- mtm_enable_core(cpu);
- }
- struct plat_smp_ops plat_smp_ops = {
- .info = smp_cpuinfo_buf,
- .init_early_smp = eznps_init_cpumasks,
- .cpu_kick = eznps_smp_wakeup_cpu,
- .ipi_send = eznps_ipi_send,
- .init_per_cpu = eznps_init_per_cpu,
- };
|