1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright(c) 2015 EZchip Technologies.
7 #include <linux/init.h>
8 #include <linux/kernel.h>
10 #include <linux/log2.h>
11 #include <asm/arcregs.h>
15 #define MT_HS_CNT_MIN 0x01
16 #define MT_HS_CNT_MAX 0xFF
17 #define MT_CTRL_ST_CNT 0xF
18 #define NPS_NUM_HW_THREADS 0x10
20 static int mtm_hs_ctr
= MT_HS_CNT_MAX
;
22 #ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
23 int do_memory_error(unsigned long address
, struct pt_regs
*regs
)
25 die("Invalid Mem Access", regs
, address
);
31 static void mtm_init_nat(int cpu
)
33 struct nps_host_reg_mtm_cfg mtm_cfg
;
34 struct nps_host_reg_aux_udmc udmc
;
35 int log_nat
, nat
= 0, i
, t
;
37 /* Iterate core threads and update nat */
38 for (i
= 0, t
= cpu
; i
< NPS_NUM_HW_THREADS
; i
++, t
++)
39 nat
+= test_bit(t
, cpumask_bits(cpu_possible_mask
));
43 udmc
.value
= read_aux_reg(CTOP_AUX_UDMC
);
45 write_aux_reg(CTOP_AUX_UDMC
, udmc
.value
);
47 mtm_cfg
.value
= ioread32be(MTM_CFG(cpu
));
48 mtm_cfg
.nat
= log_nat
;
49 iowrite32be(mtm_cfg
.value
, MTM_CFG(cpu
));
52 static void mtm_init_thread(int cpu
)
55 struct nps_host_reg_thr_init thr_init
;
56 struct nps_host_reg_thr_init_sts thr_init_sts
;
58 /* Set thread init register */
60 iowrite32be(thr_init
.value
, MTM_THR_INIT(cpu
));
61 thr_init
.thr_id
= NPS_CPU_TO_THREAD_NUM(cpu
);
63 iowrite32be(thr_init
.value
, MTM_THR_INIT(cpu
));
65 /* Poll till thread init is done */
66 for (i
= 0; i
< tries
; i
++) {
67 thr_init_sts
.value
= ioread32be(MTM_THR_INIT_STS(cpu
));
68 if (thr_init_sts
.thr_id
== thr_init
.thr_id
) {
71 else if (thr_init_sts
.err
)
72 pr_warn("Failed to thread init cpu %u\n", cpu
);
76 pr_warn("Wrong thread id in thread init for cpu %u\n", cpu
);
81 pr_warn("Got thread init timeout for cpu %u\n", cpu
);
84 int mtm_enable_thread(int cpu
)
86 struct nps_host_reg_mtm_cfg mtm_cfg
;
88 if (NPS_CPU_TO_THREAD_NUM(cpu
) == 0)
91 /* Enable thread in mtm */
92 mtm_cfg
.value
= ioread32be(MTM_CFG(cpu
));
93 mtm_cfg
.ten
|= (1 << (NPS_CPU_TO_THREAD_NUM(cpu
)));
94 iowrite32be(mtm_cfg
.value
, MTM_CFG(cpu
));
99 void mtm_enable_core(unsigned int cpu
)
102 struct nps_host_reg_aux_mt_ctrl mt_ctrl
;
103 struct nps_host_reg_mtm_cfg mtm_cfg
;
104 struct nps_host_reg_aux_dpc dpc
;
107 * Initializing dpc register in each CPU.
108 * Overwriting the init value of the DPC
109 * register so that CMEM and FMT virtual address
110 * spaces are accessible, and Data Plane HW
111 * facilities are enabled.
115 write_aux_reg(CTOP_AUX_DPC
, dpc
.value
);
117 if (NPS_CPU_TO_THREAD_NUM(cpu
) != 0)
120 /* Initialize Number of Active Threads */
123 /* Initialize mtm_cfg */
124 mtm_cfg
.value
= ioread32be(MTM_CFG(cpu
));
126 iowrite32be(mtm_cfg
.value
, MTM_CFG(cpu
));
128 /* Initialize all other threads in core */
129 for (i
= 1; i
< NPS_NUM_HW_THREADS
; i
++)
130 mtm_init_thread(cpu
+ i
);
133 /* Enable HW schedule, stall counter, mtm */
136 mt_ctrl
.hs_cnt
= mtm_hs_ctr
;
138 write_aux_reg(CTOP_AUX_MT_CTRL
, mt_ctrl
.value
);
141 * HW scheduling mechanism will start working
142 * Only after call to instruction "schd.rw".
143 * cpu_relax() calls "schd.rw" instruction.
148 /* Verify and set the value of the mtm hs counter */
149 static int __init
set_mtm_hs_ctr(char *ctr_str
)
154 ret
= kstrtoint(ctr_str
, 0, &hs_ctr
);
156 if (ret
|| hs_ctr
> MT_HS_CNT_MAX
|| hs_ctr
< MT_HS_CNT_MIN
) {
157 pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n",
158 hs_ctr
, MT_HS_CNT_MIN
, MT_HS_CNT_MAX
);
166 early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr
);