• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright(c) 2015 EZchip Technologies.
4  */
5 
6 #include <linux/smp.h>
7 #include <linux/init.h>
8 #include <linux/kernel.h>
9 #include <linux/io.h>
10 #include <linux/log2.h>
11 #include <asm/arcregs.h>
12 #include <plat/mtm.h>
13 #include <plat/smp.h>
14 
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
19 
20 static int mtm_hs_ctr = MT_HS_CNT_MAX;
21 
22 #ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
do_memory_error(unsigned long address,struct pt_regs * regs)23 int do_memory_error(unsigned long address, struct pt_regs *regs)
24 {
25 	die("Invalid Mem Access", regs, address);
26 
27 	return 1;
28 }
29 #endif
30 
mtm_init_nat(int cpu)31 static void mtm_init_nat(int cpu)
32 {
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;
36 
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));
40 
41 	log_nat = ilog2(nat);
42 
43 	udmc.value = read_aux_reg(CTOP_AUX_UDMC);
44 	udmc.nat = log_nat;
45 	write_aux_reg(CTOP_AUX_UDMC, udmc.value);
46 
47 	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
48 	mtm_cfg.nat = log_nat;
49 	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
50 }
51 
mtm_init_thread(int cpu)52 static void mtm_init_thread(int cpu)
53 {
54 	int i, tries = 5;
55 	struct nps_host_reg_thr_init thr_init;
56 	struct nps_host_reg_thr_init_sts thr_init_sts;
57 
58 	/* Set thread init register */
59 	thr_init.value = 0;
60 	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
61 	thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
62 	thr_init.str = 1;
63 	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
64 
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) {
69 			if (thr_init_sts.bsy)
70 				continue;
71 			else if (thr_init_sts.err)
72 				pr_warn("Failed to thread init cpu %u\n", cpu);
73 			break;
74 		}
75 
76 		pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
77 		break;
78 	}
79 
80 	if (i == tries)
81 		pr_warn("Got thread init timeout for cpu %u\n", cpu);
82 }
83 
mtm_enable_thread(int cpu)84 int mtm_enable_thread(int cpu)
85 {
86 	struct nps_host_reg_mtm_cfg mtm_cfg;
87 
88 	if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
89 		return 1;
90 
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));
95 
96 	return 0;
97 }
98 
mtm_enable_core(unsigned int cpu)99 void mtm_enable_core(unsigned int cpu)
100 {
101 	int i;
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;
105 
106 	/*
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.
112 	 */
113 	dpc.ien = 1;
114 	dpc.men = 1;
115 	write_aux_reg(CTOP_AUX_DPC, dpc.value);
116 
117 	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
118 		return;
119 
120 	/* Initialize Number of Active Threads */
121 	mtm_init_nat(cpu);
122 
123 	/* Initialize mtm_cfg */
124 	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
125 	mtm_cfg.ten = 1;
126 	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
127 
128 	/* Initialize all other threads in core */
129 	for (i = 1; i < NPS_NUM_HW_THREADS; i++)
130 		mtm_init_thread(cpu + i);
131 
132 
133 	/* Enable HW schedule, stall counter, mtm */
134 	mt_ctrl.value = 0;
135 	mt_ctrl.hsen = 1;
136 	mt_ctrl.hs_cnt = mtm_hs_ctr;
137 	mt_ctrl.mten = 1;
138 	write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
139 
140 	/*
141 	 * HW scheduling mechanism will start working
142 	 * Only after call to instruction "schd.rw".
143 	 * cpu_relax() calls "schd.rw" instruction.
144 	 */
145 	cpu_relax();
146 }
147 
148 /* Verify and set the value of the mtm hs counter */
set_mtm_hs_ctr(char * ctr_str)149 static int __init set_mtm_hs_ctr(char *ctr_str)
150 {
151 	int hs_ctr;
152 	int ret;
153 
154 	ret = kstrtoint(ctr_str, 0, &hs_ctr);
155 
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);
159 		return -EINVAL;
160 	}
161 
162 	mtm_hs_ctr = hs_ctr;
163 
164 	return 0;
165 }
166 early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);
167