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/init.h>
19 #include <linux/kernel.h>
21 #include <linux/log2.h>
22 #include <asm/arcregs.h>
26 #define MT_HS_CNT_MIN 0x01
27 #define MT_HS_CNT_MAX 0xFF
28 #define MT_CTRL_ST_CNT 0xF
29 #define NPS_NUM_HW_THREADS 0x10
31 static int mtm_hs_ctr = MT_HS_CNT_MAX;
33 #ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
34 int do_memory_error(unsigned long address, struct pt_regs *regs)
36 die("Invalid Mem Access", regs, address);
42 static void mtm_init_nat(int cpu)
44 struct nps_host_reg_mtm_cfg mtm_cfg;
45 struct nps_host_reg_aux_udmc udmc;
46 int log_nat, nat = 0, i, t;
48 /* Iterate core threads and update nat */
49 for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
50 nat += test_bit(t, cpumask_bits(cpu_possible_mask));
54 udmc.value = read_aux_reg(CTOP_AUX_UDMC);
56 write_aux_reg(CTOP_AUX_UDMC, udmc.value);
58 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
59 mtm_cfg.nat = log_nat;
60 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
63 static void mtm_init_thread(int cpu)
66 struct nps_host_reg_thr_init thr_init;
67 struct nps_host_reg_thr_init_sts thr_init_sts;
69 /* Set thread init register */
71 iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
72 thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
74 iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
76 /* Poll till thread init is done */
77 for (i = 0; i < tries; i++) {
78 thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
79 if (thr_init_sts.thr_id == thr_init.thr_id) {
82 else if (thr_init_sts.err)
83 pr_warn("Failed to thread init cpu %u\n", cpu);
87 pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
92 pr_warn("Got thread init timeout for cpu %u\n", cpu);
95 int mtm_enable_thread(int cpu)
97 struct nps_host_reg_mtm_cfg mtm_cfg;
99 if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
102 /* Enable thread in mtm */
103 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
104 mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
105 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
110 void mtm_enable_core(unsigned int cpu)
113 struct nps_host_reg_aux_mt_ctrl mt_ctrl;
114 struct nps_host_reg_mtm_cfg mtm_cfg;
115 struct nps_host_reg_aux_dpc dpc;
118 * Initializing dpc register in each CPU.
119 * Overwriting the init value of the DPC
120 * register so that CMEM and FMT virtual address
121 * spaces are accessible, and Data Plane HW
122 * facilities are enabled.
126 write_aux_reg(CTOP_AUX_DPC, dpc.value);
128 if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
131 /* Initialize Number of Active Threads */
134 /* Initialize mtm_cfg */
135 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
137 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
139 /* Initialize all other threads in core */
140 for (i = 1; i < NPS_NUM_HW_THREADS; i++)
141 mtm_init_thread(cpu + i);
144 /* Enable HW schedule, stall counter, mtm */
147 mt_ctrl.hs_cnt = mtm_hs_ctr;
149 write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
152 * HW scheduling mechanism will start working
153 * Only after call to instruction "schd.rw".
154 * cpu_relax() calls "schd.rw" instruction.
159 /* Verify and set the value of the mtm hs counter */
160 static int __init set_mtm_hs_ctr(char *ctr_str)
165 ret = kstrtoint(ctr_str, 0, &hs_ctr);
167 if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) {
168 pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n",
169 hs_ctr, MT_HS_CNT_MIN, MT_HS_CNT_MAX);
177 early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);