1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2013 Imagination Technologies |
4 | * Author: Paul Burton <paul.burton@mips.com> |
5 | */ |
6 | |
7 | #include <linux/errno.h> |
8 | #include <linux/percpu.h> |
9 | #include <linux/spinlock.h> |
10 | |
11 | #include <asm/mips-cps.h> |
12 | #include <asm/mipsregs.h> |
13 | |
14 | void __iomem *mips_gcr_base; |
15 | void __iomem *mips_cm_l2sync_base; |
16 | int mips_cm_is64; |
17 | |
18 | static char *cm2_tr[8] = { |
19 | "mem" , "gcr" , "gic" , "mmio" , |
20 | "0x04" , "cpc" , "0x06" , "0x07" |
21 | }; |
22 | |
23 | /* CM3 Tag ECC transaction type */ |
24 | static char *cm3_tr[16] = { |
25 | [0x0] = "ReqNoData" , |
26 | [0x1] = "0x1" , |
27 | [0x2] = "ReqWData" , |
28 | [0x3] = "0x3" , |
29 | [0x4] = "IReqNoResp" , |
30 | [0x5] = "IReqWResp" , |
31 | [0x6] = "IReqNoRespDat" , |
32 | [0x7] = "IReqWRespDat" , |
33 | [0x8] = "RespNoData" , |
34 | [0x9] = "RespDataFol" , |
35 | [0xa] = "RespWData" , |
36 | [0xb] = "RespDataOnly" , |
37 | [0xc] = "IRespNoData" , |
38 | [0xd] = "IRespDataFol" , |
39 | [0xe] = "IRespWData" , |
40 | [0xf] = "IRespDataOnly" |
41 | }; |
42 | |
43 | static char *cm2_cmd[32] = { |
44 | [0x00] = "0x00" , |
45 | [0x01] = "Legacy Write" , |
46 | [0x02] = "Legacy Read" , |
47 | [0x03] = "0x03" , |
48 | [0x04] = "0x04" , |
49 | [0x05] = "0x05" , |
50 | [0x06] = "0x06" , |
51 | [0x07] = "0x07" , |
52 | [0x08] = "Coherent Read Own" , |
53 | [0x09] = "Coherent Read Share" , |
54 | [0x0a] = "Coherent Read Discard" , |
55 | [0x0b] = "Coherent Ready Share Always" , |
56 | [0x0c] = "Coherent Upgrade" , |
57 | [0x0d] = "Coherent Writeback" , |
58 | [0x0e] = "0x0e" , |
59 | [0x0f] = "0x0f" , |
60 | [0x10] = "Coherent Copyback" , |
61 | [0x11] = "Coherent Copyback Invalidate" , |
62 | [0x12] = "Coherent Invalidate" , |
63 | [0x13] = "Coherent Write Invalidate" , |
64 | [0x14] = "Coherent Completion Sync" , |
65 | [0x15] = "0x15" , |
66 | [0x16] = "0x16" , |
67 | [0x17] = "0x17" , |
68 | [0x18] = "0x18" , |
69 | [0x19] = "0x19" , |
70 | [0x1a] = "0x1a" , |
71 | [0x1b] = "0x1b" , |
72 | [0x1c] = "0x1c" , |
73 | [0x1d] = "0x1d" , |
74 | [0x1e] = "0x1e" , |
75 | [0x1f] = "0x1f" |
76 | }; |
77 | |
78 | /* CM3 Tag ECC command type */ |
79 | static char *cm3_cmd[16] = { |
80 | [0x0] = "Legacy Read" , |
81 | [0x1] = "Legacy Write" , |
82 | [0x2] = "Coherent Read Own" , |
83 | [0x3] = "Coherent Read Share" , |
84 | [0x4] = "Coherent Read Discard" , |
85 | [0x5] = "Coherent Evicted" , |
86 | [0x6] = "Coherent Upgrade" , |
87 | [0x7] = "Coherent Upgrade for Store Conditional" , |
88 | [0x8] = "Coherent Writeback" , |
89 | [0x9] = "Coherent Write Invalidate" , |
90 | [0xa] = "0xa" , |
91 | [0xb] = "0xb" , |
92 | [0xc] = "0xc" , |
93 | [0xd] = "0xd" , |
94 | [0xe] = "0xe" , |
95 | [0xf] = "0xf" |
96 | }; |
97 | |
98 | /* CM3 Tag ECC command group */ |
99 | static char *cm3_cmd_group[8] = { |
100 | [0x0] = "Normal" , |
101 | [0x1] = "Registers" , |
102 | [0x2] = "TLB" , |
103 | [0x3] = "0x3" , |
104 | [0x4] = "L1I" , |
105 | [0x5] = "L1D" , |
106 | [0x6] = "L3" , |
107 | [0x7] = "L2" |
108 | }; |
109 | |
110 | static char *cm2_core[8] = { |
111 | "Invalid/OK" , "Invalid/Data" , |
112 | "Shared/OK" , "Shared/Data" , |
113 | "Modified/OK" , "Modified/Data" , |
114 | "Exclusive/OK" , "Exclusive/Data" |
115 | }; |
116 | |
117 | static char *cm2_l2_type[4] = { |
118 | [0x0] = "None" , |
119 | [0x1] = "Tag RAM single/double ECC error" , |
120 | [0x2] = "Data RAM single/double ECC error" , |
121 | [0x3] = "WS RAM uncorrectable dirty parity" |
122 | }; |
123 | |
124 | static char *cm2_l2_instr[32] = { |
125 | [0x00] = "L2_NOP" , |
126 | [0x01] = "L2_ERR_CORR" , |
127 | [0x02] = "L2_TAG_INV" , |
128 | [0x03] = "L2_WS_CLEAN" , |
129 | [0x04] = "L2_RD_MDYFY_WR" , |
130 | [0x05] = "L2_WS_MRU" , |
131 | [0x06] = "L2_EVICT_LN2" , |
132 | [0x07] = "0x07" , |
133 | [0x08] = "L2_EVICT" , |
134 | [0x09] = "L2_REFL" , |
135 | [0x0a] = "L2_RD" , |
136 | [0x0b] = "L2_WR" , |
137 | [0x0c] = "L2_EVICT_MRU" , |
138 | [0x0d] = "L2_SYNC" , |
139 | [0x0e] = "L2_REFL_ERR" , |
140 | [0x0f] = "0x0f" , |
141 | [0x10] = "L2_INDX_WB_INV" , |
142 | [0x11] = "L2_INDX_LD_TAG" , |
143 | [0x12] = "L2_INDX_ST_TAG" , |
144 | [0x13] = "L2_INDX_ST_DATA" , |
145 | [0x14] = "L2_INDX_ST_ECC" , |
146 | [0x15] = "0x15" , |
147 | [0x16] = "0x16" , |
148 | [0x17] = "0x17" , |
149 | [0x18] = "L2_FTCH_AND_LCK" , |
150 | [0x19] = "L2_HIT_INV" , |
151 | [0x1a] = "L2_HIT_WB_INV" , |
152 | [0x1b] = "L2_HIT_WB" , |
153 | [0x1c] = "0x1c" , |
154 | [0x1d] = "0x1d" , |
155 | [0x1e] = "0x1e" , |
156 | [0x1f] = "0x1f" |
157 | }; |
158 | |
159 | static char *cm2_causes[32] = { |
160 | "None" , "GC_WR_ERR" , "GC_RD_ERR" , "COH_WR_ERR" , |
161 | "COH_RD_ERR" , "MMIO_WR_ERR" , "MMIO_RD_ERR" , "0x07" , |
162 | "0x08" , "0x09" , "0x0a" , "0x0b" , |
163 | "0x0c" , "0x0d" , "0x0e" , "0x0f" , |
164 | "0x10" , "INTVN_WR_ERR" , "INTVN_RD_ERR" , "0x13" , |
165 | "0x14" , "0x15" , "0x16" , "0x17" , |
166 | "L2_RD_UNCORR" , "L2_WR_UNCORR" , "L2_CORR" , "0x1b" , |
167 | "0x1c" , "0x1d" , "0x1e" , "0x1f" |
168 | }; |
169 | |
170 | static char *cm3_causes[32] = { |
171 | "0x0" , "MP_CORRECTABLE_ECC_ERR" , "MP_REQUEST_DECODE_ERR" , |
172 | "MP_UNCORRECTABLE_ECC_ERR" , "MP_PARITY_ERR" , "MP_COHERENCE_ERR" , |
173 | "CMBIU_REQUEST_DECODE_ERR" , "CMBIU_PARITY_ERR" , "CMBIU_AXI_RESP_ERR" , |
174 | "0x9" , "RBI_BUS_ERR" , "0xb" , "0xc" , "0xd" , "0xe" , "0xf" , "0x10" , |
175 | "0x11" , "0x12" , "0x13" , "0x14" , "0x15" , "0x16" , "0x17" , "0x18" , |
176 | "0x19" , "0x1a" , "0x1b" , "0x1c" , "0x1d" , "0x1e" , "0x1f" |
177 | }; |
178 | |
179 | static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock); |
180 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags); |
181 | |
182 | phys_addr_t __weak mips_cm_phys_base(void) |
183 | { |
184 | unsigned long cmgcr; |
185 | |
186 | /* Check the CMGCRBase register is implemented */ |
187 | if (!(read_c0_config() & MIPS_CONF_M)) |
188 | return 0; |
189 | |
190 | if (!(read_c0_config2() & MIPS_CONF_M)) |
191 | return 0; |
192 | |
193 | if (!(read_c0_config3() & MIPS_CONF3_CMGCR)) |
194 | return 0; |
195 | |
196 | /* Read the address from CMGCRBase */ |
197 | cmgcr = read_c0_cmgcrbase(); |
198 | return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32); |
199 | } |
200 | |
201 | phys_addr_t __weak mips_cm_l2sync_phys_base(void) |
202 | { |
203 | u32 base_reg; |
204 | |
205 | /* |
206 | * If the L2-only sync region is already enabled then leave it at it's |
207 | * current location. |
208 | */ |
209 | base_reg = read_gcr_l2_only_sync_base(); |
210 | if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN) |
211 | return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE; |
212 | |
213 | /* Default to following the CM */ |
214 | return mips_cm_phys_base() + MIPS_CM_GCR_SIZE; |
215 | } |
216 | |
217 | static void mips_cm_probe_l2sync(void) |
218 | { |
219 | unsigned major_rev; |
220 | phys_addr_t addr; |
221 | |
222 | /* L2-only sync was introduced with CM major revision 6 */ |
223 | major_rev = FIELD_GET(CM_GCR_REV_MAJOR, read_gcr_rev()); |
224 | if (major_rev < 6) |
225 | return; |
226 | |
227 | /* Find a location for the L2 sync region */ |
228 | addr = mips_cm_l2sync_phys_base(); |
229 | BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE) != addr); |
230 | if (!addr) |
231 | return; |
232 | |
233 | /* Set the region base address & enable it */ |
234 | write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN); |
235 | |
236 | /* Map the region */ |
237 | mips_cm_l2sync_base = ioremap(addr, MIPS_CM_L2SYNC_SIZE); |
238 | } |
239 | |
240 | int mips_cm_probe(void) |
241 | { |
242 | phys_addr_t addr; |
243 | u32 base_reg; |
244 | unsigned cpu; |
245 | |
246 | /* |
247 | * No need to probe again if we have already been |
248 | * here before. |
249 | */ |
250 | if (mips_gcr_base) |
251 | return 0; |
252 | |
253 | addr = mips_cm_phys_base(); |
254 | BUG_ON((addr & CM_GCR_BASE_GCRBASE) != addr); |
255 | if (!addr) |
256 | return -ENODEV; |
257 | |
258 | mips_gcr_base = ioremap(addr, MIPS_CM_GCR_SIZE); |
259 | if (!mips_gcr_base) |
260 | return -ENXIO; |
261 | |
262 | /* sanity check that we're looking at a CM */ |
263 | base_reg = read_gcr_base(); |
264 | if ((base_reg & CM_GCR_BASE_GCRBASE) != addr) { |
265 | pr_err("GCRs appear to have been moved (expected them at 0x%08lx)!\n" , |
266 | (unsigned long)addr); |
267 | iounmap(mips_gcr_base); |
268 | mips_gcr_base = NULL; |
269 | return -ENODEV; |
270 | } |
271 | |
272 | /* set default target to memory */ |
273 | change_gcr_base(CM_GCR_BASE_CMDEFTGT, CM_GCR_BASE_CMDEFTGT_MEM); |
274 | |
275 | /* disable CM regions */ |
276 | write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR); |
277 | write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK); |
278 | write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR); |
279 | write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK); |
280 | write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR); |
281 | write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK); |
282 | write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR); |
283 | write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK); |
284 | |
285 | /* probe for an L2-only sync region */ |
286 | mips_cm_probe_l2sync(); |
287 | |
288 | /* determine register width for this CM */ |
289 | mips_cm_is64 = IS_ENABLED(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3); |
290 | |
291 | for_each_possible_cpu(cpu) |
292 | spin_lock_init(&per_cpu(cm_core_lock, cpu)); |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | void mips_cm_lock_other(unsigned int cluster, unsigned int core, |
298 | unsigned int vp, unsigned int block) |
299 | { |
300 | unsigned int curr_core, cm_rev; |
301 | u32 val; |
302 | |
303 | cm_rev = mips_cm_revision(); |
304 | preempt_disable(); |
305 | |
306 | if (cm_rev >= CM_REV_CM3) { |
307 | val = FIELD_PREP(CM3_GCR_Cx_OTHER_CORE, core) | |
308 | FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp); |
309 | |
310 | if (cm_rev >= CM_REV_CM3_5) { |
311 | val |= CM_GCR_Cx_OTHER_CLUSTER_EN; |
312 | val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster); |
313 | val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block); |
314 | } else { |
315 | WARN_ON(cluster != 0); |
316 | WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); |
317 | } |
318 | |
319 | /* |
320 | * We need to disable interrupts in SMP systems in order to |
321 | * ensure that we don't interrupt the caller with code which |
322 | * may modify the redirect register. We do so here in a |
323 | * slightly obscure way by using a spin lock, since this has |
324 | * the neat property of also catching any nested uses of |
325 | * mips_cm_lock_other() leading to a deadlock or a nice warning |
326 | * with lockdep enabled. |
327 | */ |
328 | spin_lock_irqsave(this_cpu_ptr(&cm_core_lock), |
329 | *this_cpu_ptr(&cm_core_lock_flags)); |
330 | } else { |
331 | WARN_ON(cluster != 0); |
332 | WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); |
333 | |
334 | /* |
335 | * We only have a GCR_CL_OTHER per core in systems with |
336 | * CM 2.5 & older, so have to ensure other VP(E)s don't |
337 | * race with us. |
338 | */ |
339 | curr_core = cpu_core(¤t_cpu_data); |
340 | spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), |
341 | per_cpu(cm_core_lock_flags, curr_core)); |
342 | |
343 | val = FIELD_PREP(CM_GCR_Cx_OTHER_CORENUM, core); |
344 | } |
345 | |
346 | write_gcr_cl_other(val); |
347 | |
348 | /* |
349 | * Ensure the core-other region reflects the appropriate core & |
350 | * VP before any accesses to it occur. |
351 | */ |
352 | mb(); |
353 | } |
354 | |
355 | void mips_cm_unlock_other(void) |
356 | { |
357 | unsigned int curr_core; |
358 | |
359 | if (mips_cm_revision() < CM_REV_CM3) { |
360 | curr_core = cpu_core(¤t_cpu_data); |
361 | spin_unlock_irqrestore(lock: &per_cpu(cm_core_lock, curr_core), |
362 | per_cpu(cm_core_lock_flags, curr_core)); |
363 | } else { |
364 | spin_unlock_irqrestore(this_cpu_ptr(&cm_core_lock), |
365 | flags: *this_cpu_ptr(&cm_core_lock_flags)); |
366 | } |
367 | |
368 | preempt_enable(); |
369 | } |
370 | |
371 | void mips_cm_error_report(void) |
372 | { |
373 | u64 cm_error, cm_addr, cm_other; |
374 | unsigned long revision; |
375 | int ocause, cause; |
376 | char buf[256]; |
377 | |
378 | if (!mips_cm_present()) |
379 | return; |
380 | |
381 | revision = mips_cm_revision(); |
382 | cm_error = read_gcr_error_cause(); |
383 | cm_addr = read_gcr_error_addr(); |
384 | cm_other = read_gcr_error_mult(); |
385 | |
386 | if (revision < CM_REV_CM3) { /* CM2 */ |
387 | cause = FIELD_GET(CM_GCR_ERROR_CAUSE_ERRTYPE, cm_error); |
388 | ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); |
389 | |
390 | if (!cause) |
391 | return; |
392 | |
393 | if (cause < 16) { |
394 | unsigned long cca_bits = (cm_error >> 15) & 7; |
395 | unsigned long tr_bits = (cm_error >> 12) & 7; |
396 | unsigned long cmd_bits = (cm_error >> 7) & 0x1f; |
397 | unsigned long stag_bits = (cm_error >> 3) & 15; |
398 | unsigned long sport_bits = (cm_error >> 0) & 7; |
399 | |
400 | snprintf(buf, size: sizeof(buf), |
401 | fmt: "CCA=%lu TR=%s MCmd=%s STag=%lu " |
402 | "SPort=%lu\n" , cca_bits, cm2_tr[tr_bits], |
403 | cm2_cmd[cmd_bits], stag_bits, sport_bits); |
404 | } else if (cause < 24) { |
405 | /* glob state & sresp together */ |
406 | unsigned long c3_bits = (cm_error >> 18) & 7; |
407 | unsigned long c2_bits = (cm_error >> 15) & 7; |
408 | unsigned long c1_bits = (cm_error >> 12) & 7; |
409 | unsigned long c0_bits = (cm_error >> 9) & 7; |
410 | unsigned long sc_bit = (cm_error >> 8) & 1; |
411 | unsigned long cmd_bits = (cm_error >> 3) & 0x1f; |
412 | unsigned long sport_bits = (cm_error >> 0) & 7; |
413 | |
414 | snprintf(buf, size: sizeof(buf), |
415 | fmt: "C3=%s C2=%s C1=%s C0=%s SC=%s " |
416 | "MCmd=%s SPort=%lu\n" , |
417 | cm2_core[c3_bits], cm2_core[c2_bits], |
418 | cm2_core[c1_bits], cm2_core[c0_bits], |
419 | sc_bit ? "True" : "False" , |
420 | cm2_cmd[cmd_bits], sport_bits); |
421 | } else { |
422 | unsigned long muc_bit = (cm_error >> 23) & 1; |
423 | unsigned long ins_bits = (cm_error >> 18) & 0x1f; |
424 | unsigned long arr_bits = (cm_error >> 16) & 3; |
425 | unsigned long dw_bits = (cm_error >> 12) & 15; |
426 | unsigned long way_bits = (cm_error >> 9) & 7; |
427 | unsigned long mway_bit = (cm_error >> 8) & 1; |
428 | unsigned long syn_bits = (cm_error >> 0) & 0xFF; |
429 | |
430 | snprintf(buf, size: sizeof(buf), |
431 | fmt: "Type=%s%s Instr=%s DW=%lu Way=%lu " |
432 | "MWay=%s Syndrome=0x%02lx" , |
433 | muc_bit ? "Multi-UC " : "" , |
434 | cm2_l2_type[arr_bits], |
435 | cm2_l2_instr[ins_bits], dw_bits, way_bits, |
436 | mway_bit ? "True" : "False" , syn_bits); |
437 | } |
438 | pr_err("CM_ERROR=%08llx %s <%s>\n" , cm_error, |
439 | cm2_causes[cause], buf); |
440 | pr_err("CM_ADDR =%08llx\n" , cm_addr); |
441 | pr_err("CM_OTHER=%08llx %s\n" , cm_other, cm2_causes[ocause]); |
442 | } else { /* CM3 */ |
443 | ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits; |
444 | ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit; |
445 | |
446 | cause = FIELD_GET(CM3_GCR_ERROR_CAUSE_ERRTYPE, cm_error); |
447 | ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); |
448 | |
449 | if (!cause) |
450 | return; |
451 | |
452 | /* Used by cause == {1,2,3} */ |
453 | core_id_bits = (cm_error >> 22) & 0xf; |
454 | vp_id_bits = (cm_error >> 18) & 0xf; |
455 | cmd_bits = (cm_error >> 14) & 0xf; |
456 | cmd_group_bits = (cm_error >> 11) & 0xf; |
457 | cm3_cca_bits = (cm_error >> 8) & 7; |
458 | mcp_bits = (cm_error >> 5) & 0xf; |
459 | cm3_tr_bits = (cm_error >> 1) & 0xf; |
460 | sched_bit = cm_error & 0x1; |
461 | |
462 | if (cause == 1 || cause == 3) { /* Tag ECC */ |
463 | unsigned long tag_ecc = (cm_error >> 57) & 0x1; |
464 | unsigned long tag_way_bits = (cm_error >> 29) & 0xffff; |
465 | unsigned long dword_bits = (cm_error >> 49) & 0xff; |
466 | unsigned long data_way_bits = (cm_error >> 45) & 0xf; |
467 | unsigned long data_sets_bits = (cm_error >> 29) & 0xfff; |
468 | unsigned long bank_bit = (cm_error >> 28) & 0x1; |
469 | snprintf(buf, size: sizeof(buf), |
470 | fmt: "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)" |
471 | "Bank=%lu CoreID=%lu VPID=%lu Command=%s" |
472 | "Command Group=%s CCA=%lu MCP=%d" |
473 | "Transaction type=%s Scheduler=%lu\n" , |
474 | tag_ecc ? "TAG" : "DATA" , |
475 | tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 : |
476 | data_way_bits, bank_bit, dword_bits, |
477 | data_sets_bits, |
478 | core_id_bits, vp_id_bits, |
479 | cm3_cmd[cmd_bits], |
480 | cm3_cmd_group[cmd_group_bits], |
481 | cm3_cca_bits, 1 << mcp_bits, |
482 | cm3_tr[cm3_tr_bits], sched_bit); |
483 | } else if (cause == 2) { |
484 | unsigned long data_error_type = (cm_error >> 41) & 0xfff; |
485 | unsigned long data_decode_cmd = (cm_error >> 37) & 0xf; |
486 | unsigned long data_decode_group = (cm_error >> 34) & 0x7; |
487 | unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f; |
488 | |
489 | snprintf(buf, size: sizeof(buf), |
490 | fmt: "Decode Request Error: Type=%lu, Command=%lu" |
491 | "Command Group=%lu Destination ID=%lu" |
492 | "CoreID=%lu VPID=%lu Command=%s" |
493 | "Command Group=%s CCA=%lu MCP=%d" |
494 | "Transaction type=%s Scheduler=%lu\n" , |
495 | data_error_type, data_decode_cmd, |
496 | data_decode_group, data_decode_destination_id, |
497 | core_id_bits, vp_id_bits, |
498 | cm3_cmd[cmd_bits], |
499 | cm3_cmd_group[cmd_group_bits], |
500 | cm3_cca_bits, 1 << mcp_bits, |
501 | cm3_tr[cm3_tr_bits], sched_bit); |
502 | } else { |
503 | buf[0] = 0; |
504 | } |
505 | |
506 | pr_err("CM_ERROR=%llx %s <%s>\n" , cm_error, |
507 | cm3_causes[cause], buf); |
508 | pr_err("CM_ADDR =%llx\n" , cm_addr); |
509 | pr_err("CM_OTHER=%llx %s\n" , cm_other, cm3_causes[ocause]); |
510 | } |
511 | |
512 | /* reprime cause register */ |
513 | write_gcr_error_cause(cm_error); |
514 | } |
515 | |