ARC: [plat-eznps] Add eznps platform
authorNoam Camus <noamc@ezchip.com>
Sun, 19 Aug 2012 08:54:33 +0000 (11:54 +0300)
committerVineet Gupta <vgupta@synopsys.com>
Mon, 9 May 2016 04:02:32 +0000 (09:32 +0530)
This platform include boards:
Hardware Emulator (HE)
Simulator based upon nSIM.

Signed-off-by: Noam Camus <noamc@ezchip.com>
MAINTAINERS
arch/arc/plat-eznps/Kconfig [new file with mode: 0644]
arch/arc/plat-eznps/Makefile [new file with mode: 0644]
arch/arc/plat-eznps/entry.S [new file with mode: 0644]
arch/arc/plat-eznps/include/plat/ctop.h [new file with mode: 0644]
arch/arc/plat-eznps/include/plat/mtm.h [new file with mode: 0644]
arch/arc/plat-eznps/include/plat/smp.h [new file with mode: 0644]
arch/arc/plat-eznps/mtm.c [new file with mode: 0644]
arch/arc/plat-eznps/platform.c [new file with mode: 0644]
arch/arc/plat-eznps/smp.c [new file with mode: 0644]

index a727d99..87483fd 100644 (file)
@@ -4379,6 +4379,12 @@ S:       Maintained
 F:     drivers/video/fbdev/exynos/exynos_mipi*
 F:     include/video/exynos_mipi*
 
+EZchip NPS platform support
+M:     Noam Camus <noamc@ezchip.com>
+S:     Supported
+F:     arch/arc/plat-eznps
+F:     arch/arc/boot/dts/eznps.dts
+
 F71805F HARDWARE MONITORING DRIVER
 M:     Jean Delvare <jdelvare@suse.com>
 L:     linux-hwmon@vger.kernel.org
diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig
new file mode 100644 (file)
index 0000000..1d175cc
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+menuconfig ARC_PLAT_EZNPS
+       bool "\"EZchip\" ARC dev platform"
+       select ARC_HAS_COH_CACHES if SMP
+       select CPU_BIG_ENDIAN
+       select CLKSRC_NPS
+       select EZNPS_GIC
+       select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
+       help
+         Support for EZchip development platforms,
+         based on ARC700 cores.
+         We handle few flavours:
+           - Hardware Emulator AKA HE which is FPGA based chasis
+           - Simulator based on MetaWare nSIM
+           - NPS400 chip based on ASIC
+
+config EZNPS_MTM_EXT
+       bool "ARC-EZchip MTM Extensions"
+       select CPUMASK_OFFSTACK
+       depends on ARC_PLAT_EZNPS && SMP
+       default y
+       help
+         Here we add new hierarchy for CPUs topology.
+         We got:
+               Core
+               Thread
+         At the new thread level each CPU represent one HW thread.
+         At highest hierarchy each core contain 16 threads,
+         any of them seem like CPU from Linux point of view.
+         All threads within same core share the execution unit of the
+         core and HW scheduler round robin between them.
diff --git a/arch/arc/plat-eznps/Makefile b/arch/arc/plat-eznps/Makefile
new file mode 100644 (file)
index 0000000..21091b1
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := entry.o platform.o
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
diff --git a/arch/arc/plat-eznps/entry.S b/arch/arc/plat-eznps/entry.S
new file mode 100644 (file)
index 0000000..328261c
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+
+  EZNPS CPU startup Code
+  Copyright(c) 2012 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/linkage.h>
+#include <asm/entry.h>
+#include <asm/cache.h>
+#include <plat/ctop.h>
+
+       .cpu A7
+
+       .section .init.text, "ax",@progbits
+       .align 1024     ; HW requierment for restart first PC
+
+ENTRY(res_service)
+#ifdef CONFIG_EZNPS_MTM_EXT
+       ; There is no work for HW thread id != 0
+       lr      r3, [CTOP_AUX_THREAD_ID]
+       cmp     r3, 0
+       jne     stext
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+       ; With no cache coherency mechanism D$ need to be used very carefully.
+       ; Address space:
+       ; 0G-2G: We disable CONFIG_ARC_CACHE_PAGES.
+       ; 2G-3G: We disable D$ by setting this bit.
+       ; 3G-4G: D$ is disabled by architecture.
+       ; FMT are huge pages for user application reside at 0-2G.
+       ; Only FMT left as one who can use D$ where each such page got
+       ; disable/enable bit for cachability.
+       ; Programmer will use FMT pages for private data so cache coherency
+       ; would not be a problem.
+       ; First thing we invalidate D$
+       sr      1, [ARC_REG_DC_IVDC]
+       sr      HW_COMPLY_KRN_NOT_D_CACHED, [CTOP_AUX_HW_COMPLY]
+#endif
+
+#ifdef CONFIG_SMP
+       ; We set logical cpuid to be used by GET_CPUID
+       ; We do not use physical cpuid since we want ids to be continious when
+       ; it comes to cpus on the same quad cluster.
+       ; This is useful for applications that used shared resources of a quad
+       ; cluster such SRAMS.
+       lr      r3, [CTOP_AUX_CORE_ID]
+       sr      r3, [CTOP_AUX_LOGIC_CORE_ID]
+       lr      r3, [CTOP_AUX_CLUSTER_ID]
+       ; Set logical is acheived by swap of 2 middle bits of cluster id (4 bit)
+       ; r3 is used since we use short instruction and we need q-class reg
+       .short  CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST
+       .word   CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM
+        sr     r3, [CTOP_AUX_LOGIC_CLUSTER_ID]
+#endif
+
+       j       stext
+END(res_service)
diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
new file mode 100644 (file)
index 0000000..91b25f3
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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".
+ */
+
+#ifndef _PLAT_EZNPS_CTOP_H
+#define _PLAT_EZNPS_CTOP_H
+
+#ifndef CONFIG_ARC_PLAT_EZNPS
+#error "Incorrect ctop.h include"
+#endif
+
+#include <soc/nps/common.h>
+
+/* core auxiliary registers */
+#ifdef __ASSEMBLY__
+#define CTOP_AUX_BASE                          (-0x800)
+#else
+#define CTOP_AUX_BASE                          0xFFFFF800
+#endif
+
+#define CTOP_AUX_GLOBAL_ID                     (CTOP_AUX_BASE + 0x000)
+#define CTOP_AUX_CLUSTER_ID                    (CTOP_AUX_BASE + 0x004)
+#define CTOP_AUX_CORE_ID                       (CTOP_AUX_BASE + 0x008)
+#define CTOP_AUX_THREAD_ID                     (CTOP_AUX_BASE + 0x00C)
+#define CTOP_AUX_LOGIC_GLOBAL_ID               (CTOP_AUX_BASE + 0x010)
+#define CTOP_AUX_LOGIC_CLUSTER_ID              (CTOP_AUX_BASE + 0x014)
+#define CTOP_AUX_LOGIC_CORE_ID                 (CTOP_AUX_BASE + 0x018)
+#define CTOP_AUX_MT_CTRL                       (CTOP_AUX_BASE + 0x020)
+#define CTOP_AUX_HW_COMPLY                     (CTOP_AUX_BASE + 0x024)
+#define CTOP_AUX_LPC                           (CTOP_AUX_BASE + 0x030)
+#define CTOP_AUX_EFLAGS                                (CTOP_AUX_BASE + 0x080)
+#define CTOP_AUX_IACK                          (CTOP_AUX_BASE + 0x088)
+#define CTOP_AUX_GPA1                          (CTOP_AUX_BASE + 0x08C)
+#define CTOP_AUX_UDMC                          (CTOP_AUX_BASE + 0x300)
+
+/* EZchip core instructions */
+#define CTOP_INST_HWSCHD_OFF_R3                        0x3B6F00BF
+#define CTOP_INST_HWSCHD_OFF_R4                        0x3C6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3            0x3E6F70C3
+#define CTOP_INST_HWSCHD_RESTORE_R4            0x3E6F7103
+#define CTOP_INST_SCHD_RW                      0x3E6F7004
+#define CTOP_INST_SCHD_RD                      0x3E6F7084
+#define CTOP_INST_ASRI_0_R3                    0x3B56003E
+#define CTOP_INST_XEX_DI_R2_R2_R3              0x4A664C00
+#define CTOP_INST_EXC_DI_R2_R2_R3              0x4A664C01
+#define CTOP_INST_AADD_DI_R2_R2_R3             0x4A664C02
+#define CTOP_INST_AAND_DI_R2_R2_R3             0x4A664C04
+#define CTOP_INST_AOR_DI_R2_R2_R3              0x4A664C05
+#define CTOP_INST_AXOR_DI_R2_R2_R3             0x4A664C06
+
+/* Do not use D$ for address in 2G-3G */
+#define HW_COMPLY_KRN_NOT_D_CACHED             _BITUL(28)
+
+#define NPS_MSU_EN_CFG                         0x80
+#define NPS_CRG_BLKID                          0x480
+#define NPS_CRG_SYNC_BIT                       _BITUL(0)
+#define NPS_GIM_BLKID                          0x5C0
+
+/* GIM registers and fields*/
+#define NPS_GIM_UART_LINE                      _BITUL(7)
+#define NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE      _BITUL(10)
+#define NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE       _BITUL(11)
+#define NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE      _BITUL(25)
+#define NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE       _BITUL(26)
+
+#ifndef __ASSEMBLY__
+/* Functional registers definition */
+struct nps_host_reg_mtm_cfg {
+       union {
+               struct {
+                       u32 gen:1, gdis:1, clk_gate_dis:1, asb:1,
+                       __reserved:9, nat:3, ten:16;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_mtm_cpu_cfg {
+       union {
+               struct {
+                       u32 csa:22, dmsid:6, __reserved:3, cs:1;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_thr_init {
+       union {
+               struct {
+                       u32 str:1, __reserved:27, thr_id:4;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_thr_init_sts {
+       union {
+               struct {
+                       u32 bsy:1, err:1, __reserved:26, thr_id:4;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_msu_en_cfg {
+       union {
+               struct {
+                       u32     __reserved1:11,
+                       rtc_en:1, ipc_en:1, gim_1_en:1,
+                       gim_0_en:1, ipi_en:1, buff_e_rls_bmuw:1,
+                       buff_e_alc_bmuw:1, buff_i_rls_bmuw:1, buff_i_alc_bmuw:1,
+                       buff_e_rls_bmue:1, buff_e_alc_bmue:1, buff_i_rls_bmue:1,
+                       buff_i_alc_bmue:1, __reserved2:1, buff_e_pre_en:1,
+                       buff_i_pre_en:1, pmuw_ja_en:1, pmue_ja_en:1,
+                       pmuw_nj_en:1, pmue_nj_en:1, msu_en:1;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_gim_p_int_dst {
+       union {
+               struct {
+                       u32 int_out_en:1, __reserved1:4,
+                       is:1, intm:2, __reserved2:4,
+                       nid:4, __reserved3:4, cid:4,
+                        __reserved4:4, tid:4;
+               };
+               u32 value;
+       };
+};
+
+/* AUX registers definition */
+struct nps_host_reg_aux_udmc {
+       union {
+               struct {
+                       u32 dcp:1, cme:1, __reserved:19, nat:3,
+                       __reserved2:5, dcas:3;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_aux_mt_ctrl {
+       union {
+               struct {
+                       u32 mten:1, hsen:1, scd:1, sten:1,
+                       st_cnt:8, __reserved:8,
+                       hs_cnt:8, __reserved1:4;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_aux_hw_comply {
+       union {
+               struct {
+                       u32 me:1, le:1, te:1, knc:1, __reserved:28;
+               };
+               u32 value;
+       };
+};
+
+struct nps_host_reg_aux_lpc {
+       union {
+               struct {
+                       u32 mep:1, __reserved:31;
+               };
+               u32 value;
+       };
+};
+
+/* CRG registers */
+#define REG_GEN_PURP_0          nps_host_reg_non_cl(NPS_CRG_BLKID, 0x1BF)
+
+/* GIM registers */
+#define REG_GIM_P_INT_EN_0      nps_host_reg_non_cl(NPS_GIM_BLKID, 0x100)
+#define REG_GIM_P_INT_POL_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x110)
+#define REG_GIM_P_INT_SENS_0    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x114)
+#define REG_GIM_P_INT_BLK_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x118)
+#define REG_GIM_P_INT_DST_10    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13A)
+#define REG_GIM_P_INT_DST_11    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13B)
+#define REG_GIM_P_INT_DST_25    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149)
+#define REG_GIM_P_INT_DST_26    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PLAT_EZNPS_CTOP_H */
diff --git a/arch/arc/plat-eznps/include/plat/mtm.h b/arch/arc/plat-eznps/include/plat/mtm.h
new file mode 100644 (file)
index 0000000..29b91b5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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".
+ */
+
+#ifndef _PLAT_EZNPS_MTM_H
+#define _PLAT_EZNPS_MTM_H
+
+#include <plat/ctop.h>
+
+static inline void *nps_mtm_reg_addr(u32 cpu, u32 reg)
+{
+       struct global_id gid;
+       u32 core, blkid;
+
+       gid.value = cpu;
+       core = gid.core;
+       blkid = (((core & 0x0C) << 2) | (core & 0x03));
+
+       return nps_host_reg(cpu, blkid, reg);
+}
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#define NPS_CPU_TO_THREAD_NUM(cpu) \
+       ({ struct global_id gid; gid.value = cpu; gid.thread; })
+
+/* MTM registers */
+#define MTM_CFG(cpu)                   nps_mtm_reg_addr(cpu, 0x81)
+#define MTM_THR_INIT(cpu)              nps_mtm_reg_addr(cpu, 0x92)
+#define MTM_THR_INIT_STS(cpu)          nps_mtm_reg_addr(cpu, 0x93)
+
+#define get_thread(map) map.thread
+#define eznps_max_cpus 4096
+#define eznps_cpus_per_cluster 256
+
+void mtm_enable_core(unsigned int cpu);
+int mtm_enable_thread(int cpu);
+#else /* !CONFIG_EZNPS_MTM_EXT */
+
+#define get_thread(map) 0
+#define eznps_max_cpus 256
+#define eznps_cpus_per_cluster 16
+#define mtm_enable_core(cpu)
+#define mtm_enable_thread(cpu) 1
+#define NPS_CPU_TO_THREAD_NUM(cpu) 0
+
+#endif /* CONFIG_EZNPS_MTM_EXT */
+
+#endif /* _PLAT_EZNPS_MTM_H */
diff --git a/arch/arc/plat-eznps/include/plat/smp.h b/arch/arc/plat-eznps/include/plat/smp.h
new file mode 100644 (file)
index 0000000..06b59bd
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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".
+ */
+
+#ifndef __PLAT_EZNPS_SMP_H
+#define __PLAT_EZNPS_SMP_H
+
+#ifdef CONFIG_SMP
+
+extern void res_service(void);
+
+#endif /* CONFIG_SMP */
+
+#endif
diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c
new file mode 100644 (file)
index 0000000..aaaaffd
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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/io.h>
+#include <linux/log2.h>
+#include <asm/arcregs.h>
+#include <plat/mtm.h>
+#include <plat/smp.h>
+
+#define MT_CTRL_HS_CNT         0xFF
+#define MT_CTRL_ST_CNT         0xF
+#define NPS_NUM_HW_THREADS     0x10
+
+static void mtm_init_nat(int cpu)
+{
+       struct nps_host_reg_mtm_cfg mtm_cfg;
+       struct nps_host_reg_aux_udmc udmc;
+       int log_nat, nat = 0, i, t;
+
+       /* Iterate core threads and update nat */
+       for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
+               nat += test_bit(t, cpumask_bits(cpu_possible_mask));
+
+       log_nat = ilog2(nat);
+
+       udmc.value = read_aux_reg(CTOP_AUX_UDMC);
+       udmc.nat = log_nat;
+       write_aux_reg(CTOP_AUX_UDMC, udmc.value);
+
+       mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+       mtm_cfg.nat = log_nat;
+       iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+}
+
+static void mtm_init_thread(int cpu)
+{
+       int i, tries = 5;
+       struct nps_host_reg_thr_init thr_init;
+       struct nps_host_reg_thr_init_sts thr_init_sts;
+
+       /* Set thread init register */
+       thr_init.value = 0;
+       iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+       thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
+       thr_init.str = 1;
+       iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+
+       /* Poll till thread init is done */
+       for (i = 0; i < tries; i++) {
+               thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
+               if (thr_init_sts.thr_id == thr_init.thr_id) {
+                       if (thr_init_sts.bsy)
+                               continue;
+                       else if (thr_init_sts.err)
+                               pr_warn("Failed to thread init cpu %u\n", cpu);
+                       break;
+               }
+
+               pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
+               break;
+       }
+
+       if (i == tries)
+               pr_warn("Got thread init timeout for cpu %u\n", cpu);
+}
+
+int mtm_enable_thread(int cpu)
+{
+       struct nps_host_reg_mtm_cfg mtm_cfg;
+
+       if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
+               return 1;
+
+       /* Enable thread in mtm */
+       mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+       mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
+       iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+       return 0;
+}
+
+void mtm_enable_core(unsigned int cpu)
+{
+       int i;
+       struct nps_host_reg_aux_mt_ctrl mt_ctrl;
+       struct nps_host_reg_mtm_cfg mtm_cfg;
+
+       if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+               return;
+
+       /* Initialize Number of Active Threads */
+       mtm_init_nat(cpu);
+
+       /* Initialize mtm_cfg */
+       mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+       mtm_cfg.ten = 1;
+       iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+       /* Initialize all other threads in core */
+       for (i = 1; i < NPS_NUM_HW_THREADS; i++)
+               mtm_init_thread(cpu + i);
+
+
+       /* Enable HW schedule, stall counter, mtm */
+       mt_ctrl.value = 0;
+       mt_ctrl.hsen = 1;
+       mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
+       mt_ctrl.sten = 1;
+       mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
+       mt_ctrl.mten = 1;
+       write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
+
+       /*
+        * HW scheduling mechanism will start working
+        * Only after call to instruction "schd.rw".
+        * cpu_relax() calls "schd.rw" instruction.
+        */
+       cpu_relax();
+}
diff --git a/arch/arc/plat-eznps/platform.c b/arch/arc/plat-eznps/platform.c
new file mode 100644 (file)
index 0000000..7ad6d2b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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/init.h>
+#include <linux/io.h>
+#include <asm/mach_desc.h>
+#include <plat/mtm.h>
+
+static void __init eznps_configure_msu(void)
+{
+       int cpu;
+       struct nps_host_reg_msu_en_cfg msu_en_cfg = {.value = 0};
+
+       msu_en_cfg.msu_en = 1;
+       msu_en_cfg.ipi_en = 1;
+       msu_en_cfg.gim_0_en = 1;
+       msu_en_cfg.gim_1_en = 1;
+
+       /* enable IPI and GIM messages on all clusters */
+       for (cpu = 0 ; cpu < eznps_max_cpus; cpu += eznps_cpus_per_cluster)
+               iowrite32be(msu_en_cfg.value,
+                           nps_host_reg(cpu, NPS_MSU_BLKID, NPS_MSU_EN_CFG));
+}
+
+static void __init eznps_configure_gim(void)
+{
+       u32 reg_value;
+       u32 gim_int_lines;
+       struct nps_host_reg_gim_p_int_dst gim_p_int_dst = {.value = 0};
+
+       gim_int_lines = NPS_GIM_UART_LINE;
+       gim_int_lines |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+       gim_int_lines |= NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE;
+       gim_int_lines |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+       gim_int_lines |= NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE;
+
+       /*
+        * IRQ polarity
+        * low or high level
+        * negative or positive edge
+        */
+       reg_value = ioread32be(REG_GIM_P_INT_POL_0);
+       reg_value &= ~gim_int_lines;
+       iowrite32be(reg_value, REG_GIM_P_INT_POL_0);
+
+       /* IRQ type level or edge */
+       reg_value = ioread32be(REG_GIM_P_INT_SENS_0);
+       reg_value |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+       reg_value |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+       iowrite32be(reg_value, REG_GIM_P_INT_SENS_0);
+
+       /*
+        * GIM interrupt select type for
+        * dbg_lan TX and RX interrupts
+        * should be type 1
+        * type 0 = IRQ line 6
+        * type 1 = IRQ line 7
+        */
+       gim_p_int_dst.is = 1;
+       iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_10);
+       iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_11);
+       iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_25);
+       iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_26);
+
+       /*
+        * CTOP IRQ lines should be defined
+        * as blocking in GIM
+       */
+       iowrite32be(gim_int_lines, REG_GIM_P_INT_BLK_0);
+
+       /* enable CTOP IRQ lines in GIM */
+       iowrite32be(gim_int_lines, REG_GIM_P_INT_EN_0);
+}
+
+static void __init eznps_early_init(void)
+{
+       eznps_configure_msu();
+       eznps_configure_gim();
+}
+
+static const char *eznps_compat[] __initconst = {
+       "ezchip,arc-nps",
+       NULL,
+};
+
+MACHINE_START(NPS, "nps")
+       .dt_compat      = eznps_compat,
+       .init_early     = eznps_early_init,
+MACHINE_END
diff --git a/arch/arc/plat-eznps/smp.c b/arch/arc/plat-eznps/smp.c
new file mode 100644 (file)
index 0000000..5e901f8
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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);
+}
+
+static void eznps_ipi_clear(int irq)
+{
+       write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+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,
+       .ipi_clear      = eznps_ipi_clear,
+};