1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/smp.h>
18#include <linux/io.h>
19#include <linux/log2.h>
20#include <asm/arcregs.h>
21#include <plat/mtm.h>
22#include <plat/smp.h>
23
24#define MT_HS_CNT_MIN 0x01
25#define MT_HS_CNT_MAX 0xFF
26#define MT_CTRL_ST_CNT 0xF
27#define NPS_NUM_HW_THREADS 0x10
28
29static int mtm_hs_ctr = MT_HS_CNT_MAX;
30
31#ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
32int do_memory_error(unsigned long address, struct pt_regs *regs)
33{
34 die("Invalid Mem Access", regs, address);
35
36 return 1;
37}
38#endif
39
40static void mtm_init_nat(int cpu)
41{
42 struct nps_host_reg_mtm_cfg mtm_cfg;
43 struct nps_host_reg_aux_udmc udmc;
44 int log_nat, nat = 0, i, t;
45
46
47 for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
48 nat += test_bit(t, cpumask_bits(cpu_possible_mask));
49
50 log_nat = ilog2(nat);
51
52 udmc.value = read_aux_reg(CTOP_AUX_UDMC);
53 udmc.nat = log_nat;
54 write_aux_reg(CTOP_AUX_UDMC, udmc.value);
55
56 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
57 mtm_cfg.nat = log_nat;
58 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
59}
60
61static void mtm_init_thread(int cpu)
62{
63 int i, tries = 5;
64 struct nps_host_reg_thr_init thr_init;
65 struct nps_host_reg_thr_init_sts thr_init_sts;
66
67
68 thr_init.value = 0;
69 iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
70 thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
71 thr_init.str = 1;
72 iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
73
74
75 for (i = 0; i < tries; i++) {
76 thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
77 if (thr_init_sts.thr_id == thr_init.thr_id) {
78 if (thr_init_sts.bsy)
79 continue;
80 else if (thr_init_sts.err)
81 pr_warn("Failed to thread init cpu %u\n", cpu);
82 break;
83 }
84
85 pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
86 break;
87 }
88
89 if (i == tries)
90 pr_warn("Got thread init timeout for cpu %u\n", cpu);
91}
92
93int mtm_enable_thread(int cpu)
94{
95 struct nps_host_reg_mtm_cfg mtm_cfg;
96
97 if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
98 return 1;
99
100
101 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
102 mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
103 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
104
105 return 0;
106}
107
108void mtm_enable_core(unsigned int cpu)
109{
110 int i;
111 struct nps_host_reg_aux_mt_ctrl mt_ctrl;
112 struct nps_host_reg_mtm_cfg mtm_cfg;
113 struct nps_host_reg_aux_dpc dpc;
114
115
116
117
118
119
120
121
122 dpc.ien = 1;
123 dpc.men = 1;
124 write_aux_reg(CTOP_AUX_DPC, dpc.value);
125
126 if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
127 return;
128
129
130 mtm_init_nat(cpu);
131
132
133 mtm_cfg.value = ioread32be(MTM_CFG(cpu));
134 mtm_cfg.ten = 1;
135 iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
136
137
138 for (i = 1; i < NPS_NUM_HW_THREADS; i++)
139 mtm_init_thread(cpu + i);
140
141
142
143 mt_ctrl.value = 0;
144 mt_ctrl.hsen = 1;
145 mt_ctrl.hs_cnt = mtm_hs_ctr;
146 mt_ctrl.mten = 1;
147 write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
148
149
150
151
152
153
154 cpu_relax();
155}
156
157
158static int __init set_mtm_hs_ctr(char *ctr_str)
159{
160 long hs_ctr;
161 int ret;
162
163 ret = kstrtol(ctr_str, 0, &hs_ctr);
164
165 if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) {
166 pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n",
167 hs_ctr, MT_HS_CNT_MIN, MT_HS_CNT_MAX);
168 return -EINVAL;
169 }
170
171 mtm_hs_ctr = hs_ctr;
172
173 return 0;
174}
175early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);
176