Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 Imagination Technologies |
| 3 | * Author: Paul Burton <paul.burton@imgtec.com> |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License as published by the |
| 7 | * Free Software Foundation; either version 2 of the License, or (at your |
| 8 | * option) any later version. |
| 9 | */ |
| 10 | |
| 11 | #include <linux/errno.h> |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 12 | #include <linux/percpu.h> |
| 13 | #include <linux/spinlock.h> |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 14 | |
| 15 | #include <asm/mips-cm.h> |
| 16 | #include <asm/mipsregs.h> |
| 17 | |
| 18 | void __iomem *mips_cm_base; |
| 19 | void __iomem *mips_cm_l2sync_base; |
Markos Chandras | c0b584a | 2015-07-14 09:14:12 +0100 | [diff] [blame] | 20 | int mips_cm_is64; |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 21 | |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 22 | static char *cm2_tr[8] = { |
| 23 | "mem", "gcr", "gic", "mmio", |
| 24 | "0x04", "cpc", "0x06", "0x07" |
| 25 | }; |
| 26 | |
Adam Buchbinder | 92a76f6 | 2016-02-25 00:44:58 -0800 | [diff] [blame] | 27 | /* CM3 Tag ECC transaction type */ |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 28 | static char *cm3_tr[16] = { |
| 29 | [0x0] = "ReqNoData", |
| 30 | [0x1] = "0x1", |
| 31 | [0x2] = "ReqWData", |
| 32 | [0x3] = "0x3", |
| 33 | [0x4] = "IReqNoResp", |
| 34 | [0x5] = "IReqWResp", |
| 35 | [0x6] = "IReqNoRespDat", |
| 36 | [0x7] = "IReqWRespDat", |
| 37 | [0x8] = "RespNoData", |
| 38 | [0x9] = "RespDataFol", |
| 39 | [0xa] = "RespWData", |
| 40 | [0xb] = "RespDataOnly", |
| 41 | [0xc] = "IRespNoData", |
| 42 | [0xd] = "IRespDataFol", |
| 43 | [0xe] = "IRespWData", |
| 44 | [0xf] = "IRespDataOnly" |
| 45 | }; |
| 46 | |
| 47 | static char *cm2_cmd[32] = { |
| 48 | [0x00] = "0x00", |
| 49 | [0x01] = "Legacy Write", |
| 50 | [0x02] = "Legacy Read", |
| 51 | [0x03] = "0x03", |
| 52 | [0x04] = "0x04", |
| 53 | [0x05] = "0x05", |
| 54 | [0x06] = "0x06", |
| 55 | [0x07] = "0x07", |
| 56 | [0x08] = "Coherent Read Own", |
| 57 | [0x09] = "Coherent Read Share", |
| 58 | [0x0a] = "Coherent Read Discard", |
| 59 | [0x0b] = "Coherent Ready Share Always", |
| 60 | [0x0c] = "Coherent Upgrade", |
| 61 | [0x0d] = "Coherent Writeback", |
| 62 | [0x0e] = "0x0e", |
| 63 | [0x0f] = "0x0f", |
| 64 | [0x10] = "Coherent Copyback", |
| 65 | [0x11] = "Coherent Copyback Invalidate", |
| 66 | [0x12] = "Coherent Invalidate", |
| 67 | [0x13] = "Coherent Write Invalidate", |
| 68 | [0x14] = "Coherent Completion Sync", |
| 69 | [0x15] = "0x15", |
| 70 | [0x16] = "0x16", |
| 71 | [0x17] = "0x17", |
| 72 | [0x18] = "0x18", |
| 73 | [0x19] = "0x19", |
| 74 | [0x1a] = "0x1a", |
| 75 | [0x1b] = "0x1b", |
| 76 | [0x1c] = "0x1c", |
| 77 | [0x1d] = "0x1d", |
| 78 | [0x1e] = "0x1e", |
| 79 | [0x1f] = "0x1f" |
| 80 | }; |
| 81 | |
| 82 | /* CM3 Tag ECC command type */ |
| 83 | static char *cm3_cmd[16] = { |
| 84 | [0x0] = "Legacy Read", |
| 85 | [0x1] = "Legacy Write", |
| 86 | [0x2] = "Coherent Read Own", |
| 87 | [0x3] = "Coherent Read Share", |
| 88 | [0x4] = "Coherent Read Discard", |
| 89 | [0x5] = "Coherent Evicted", |
| 90 | [0x6] = "Coherent Upgrade", |
| 91 | [0x7] = "Coherent Upgrade for Store Conditional", |
| 92 | [0x8] = "Coherent Writeback", |
| 93 | [0x9] = "Coherent Write Invalidate", |
| 94 | [0xa] = "0xa", |
| 95 | [0xb] = "0xb", |
| 96 | [0xc] = "0xc", |
| 97 | [0xd] = "0xd", |
| 98 | [0xe] = "0xe", |
| 99 | [0xf] = "0xf" |
| 100 | }; |
| 101 | |
| 102 | /* CM3 Tag ECC command group */ |
| 103 | static char *cm3_cmd_group[8] = { |
| 104 | [0x0] = "Normal", |
| 105 | [0x1] = "Registers", |
| 106 | [0x2] = "TLB", |
| 107 | [0x3] = "0x3", |
| 108 | [0x4] = "L1I", |
| 109 | [0x5] = "L1D", |
| 110 | [0x6] = "L3", |
| 111 | [0x7] = "L2" |
| 112 | }; |
| 113 | |
| 114 | static char *cm2_core[8] = { |
| 115 | "Invalid/OK", "Invalid/Data", |
| 116 | "Shared/OK", "Shared/Data", |
| 117 | "Modified/OK", "Modified/Data", |
| 118 | "Exclusive/OK", "Exclusive/Data" |
| 119 | }; |
| 120 | |
| 121 | static char *cm2_causes[32] = { |
| 122 | "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR", |
| 123 | "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07", |
| 124 | "0x08", "0x09", "0x0a", "0x0b", |
| 125 | "0x0c", "0x0d", "0x0e", "0x0f", |
| 126 | "0x10", "0x11", "0x12", "0x13", |
| 127 | "0x14", "0x15", "0x16", "INTVN_WR_ERR", |
| 128 | "INTVN_RD_ERR", "0x19", "0x1a", "0x1b", |
| 129 | "0x1c", "0x1d", "0x1e", "0x1f" |
| 130 | }; |
| 131 | |
| 132 | static char *cm3_causes[32] = { |
| 133 | "0x0", "MP_CORRECTABLE_ECC_ERR", "MP_REQUEST_DECODE_ERR", |
| 134 | "MP_UNCORRECTABLE_ECC_ERR", "MP_PARITY_ERR", "MP_COHERENCE_ERR", |
| 135 | "CMBIU_REQUEST_DECODE_ERR", "CMBIU_PARITY_ERR", "CMBIU_AXI_RESP_ERR", |
| 136 | "0x9", "RBI_BUS_ERR", "0xb", "0xc", "0xd", "0xe", "0xf", "0x10", |
| 137 | "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", |
| 138 | "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f" |
| 139 | }; |
| 140 | |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 141 | static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock); |
| 142 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags); |
| 143 | |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 144 | phys_addr_t __mips_cm_phys_base(void) |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 145 | { |
| 146 | u32 config3 = read_c0_config3(); |
Markos Chandras | 038b0f5 | 2015-07-09 10:40:45 +0100 | [diff] [blame] | 147 | unsigned long cmgcr; |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 148 | |
| 149 | /* Check the CMGCRBase register is implemented */ |
| 150 | if (!(config3 & MIPS_CONF3_CMGCR)) |
| 151 | return 0; |
| 152 | |
| 153 | /* Read the address from CMGCRBase */ |
| 154 | cmgcr = read_c0_cmgcrbase(); |
| 155 | return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32); |
| 156 | } |
| 157 | |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 158 | phys_addr_t mips_cm_phys_base(void) |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 159 | __attribute__((weak, alias("__mips_cm_phys_base"))); |
| 160 | |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 161 | phys_addr_t __mips_cm_l2sync_phys_base(void) |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 162 | { |
| 163 | u32 base_reg; |
| 164 | |
| 165 | /* |
| 166 | * If the L2-only sync region is already enabled then leave it at it's |
| 167 | * current location. |
| 168 | */ |
| 169 | base_reg = read_gcr_l2_only_sync_base(); |
| 170 | if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK) |
| 171 | return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK; |
| 172 | |
| 173 | /* Default to following the CM */ |
| 174 | return mips_cm_phys_base() + MIPS_CM_GCR_SIZE; |
| 175 | } |
| 176 | |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 177 | phys_addr_t mips_cm_l2sync_phys_base(void) |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 178 | __attribute__((weak, alias("__mips_cm_l2sync_phys_base"))); |
| 179 | |
| 180 | static void mips_cm_probe_l2sync(void) |
| 181 | { |
| 182 | unsigned major_rev; |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 183 | phys_addr_t addr; |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 184 | |
| 185 | /* L2-only sync was introduced with CM major revision 6 */ |
| 186 | major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >> |
| 187 | CM_GCR_REV_MAJOR_SHF; |
| 188 | if (major_rev < 6) |
| 189 | return; |
| 190 | |
| 191 | /* Find a location for the L2 sync region */ |
| 192 | addr = mips_cm_l2sync_phys_base(); |
| 193 | BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK) != addr); |
| 194 | if (!addr) |
| 195 | return; |
| 196 | |
| 197 | /* Set the region base address & enable it */ |
| 198 | write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK); |
| 199 | |
| 200 | /* Map the region */ |
| 201 | mips_cm_l2sync_base = ioremap_nocache(addr, MIPS_CM_L2SYNC_SIZE); |
| 202 | } |
| 203 | |
| 204 | int mips_cm_probe(void) |
| 205 | { |
Ralf Baechle | 15d45cc | 2014-11-22 00:22:09 +0100 | [diff] [blame] | 206 | phys_addr_t addr; |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 207 | u32 base_reg; |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 208 | unsigned cpu; |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 209 | |
Markos Chandras | c014d16 | 2015-07-09 10:40:43 +0100 | [diff] [blame] | 210 | /* |
| 211 | * No need to probe again if we have already been |
| 212 | * here before. |
| 213 | */ |
| 214 | if (mips_cm_base) |
| 215 | return 0; |
| 216 | |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 217 | addr = mips_cm_phys_base(); |
| 218 | BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr); |
| 219 | if (!addr) |
| 220 | return -ENODEV; |
| 221 | |
| 222 | mips_cm_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE); |
| 223 | if (!mips_cm_base) |
| 224 | return -ENXIO; |
| 225 | |
| 226 | /* sanity check that we're looking at a CM */ |
| 227 | base_reg = read_gcr_base(); |
| 228 | if ((base_reg & CM_GCR_BASE_GCRBASE_MSK) != addr) { |
| 229 | pr_err("GCRs appear to have been moved (expected them at 0x%08lx)!\n", |
| 230 | (unsigned long)addr); |
| 231 | mips_cm_base = NULL; |
| 232 | return -ENODEV; |
| 233 | } |
| 234 | |
| 235 | /* set default target to memory */ |
| 236 | base_reg &= ~CM_GCR_BASE_CMDEFTGT_MSK; |
| 237 | base_reg |= CM_GCR_BASE_CMDEFTGT_MEM; |
| 238 | write_gcr_base(base_reg); |
| 239 | |
| 240 | /* disable CM regions */ |
| 241 | write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK); |
| 242 | write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); |
| 243 | write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR_MSK); |
| 244 | write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); |
| 245 | write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR_MSK); |
| 246 | write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); |
| 247 | write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK); |
| 248 | write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); |
| 249 | |
| 250 | /* probe for an L2-only sync region */ |
| 251 | mips_cm_probe_l2sync(); |
| 252 | |
Markos Chandras | c0b584a | 2015-07-14 09:14:12 +0100 | [diff] [blame] | 253 | /* determine register width for this CM */ |
Masahiro Yamada | 97f2645 | 2016-08-03 13:45:50 -0700 | [diff] [blame] | 254 | mips_cm_is64 = IS_ENABLED(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3); |
Markos Chandras | c0b584a | 2015-07-14 09:14:12 +0100 | [diff] [blame] | 255 | |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 256 | for_each_possible_cpu(cpu) |
| 257 | spin_lock_init(&per_cpu(cm_core_lock, cpu)); |
| 258 | |
Paul Burton | 9f98f3d | 2014-01-15 10:31:51 +0000 | [diff] [blame] | 259 | return 0; |
| 260 | } |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 261 | |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 262 | void mips_cm_lock_other(unsigned int core, unsigned int vp) |
| 263 | { |
| 264 | unsigned curr_core; |
| 265 | u32 val; |
| 266 | |
| 267 | preempt_disable(); |
| 268 | curr_core = current_cpu_data.core; |
| 269 | spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), |
| 270 | per_cpu(cm_core_lock_flags, curr_core)); |
| 271 | |
| 272 | if (mips_cm_revision() >= CM_REV_CM3) { |
| 273 | val = core << CM3_GCR_Cx_OTHER_CORE_SHF; |
| 274 | val |= vp << CM3_GCR_Cx_OTHER_VP_SHF; |
| 275 | } else { |
| 276 | BUG_ON(vp != 0); |
| 277 | val = core << CM_GCR_Cx_OTHER_CORENUM_SHF; |
| 278 | } |
| 279 | |
| 280 | write_gcr_cl_other(val); |
Paul Burton | 78a54c4 | 2015-09-22 11:12:18 -0700 | [diff] [blame] | 281 | |
| 282 | /* |
| 283 | * Ensure the core-other region reflects the appropriate core & |
| 284 | * VP before any accesses to it occur. |
| 285 | */ |
| 286 | mb(); |
Paul Burton | 23d5de8 | 2015-09-22 11:12:16 -0700 | [diff] [blame] | 287 | } |
| 288 | |
| 289 | void mips_cm_unlock_other(void) |
| 290 | { |
| 291 | unsigned curr_core = current_cpu_data.core; |
| 292 | |
| 293 | spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core), |
| 294 | per_cpu(cm_core_lock_flags, curr_core)); |
| 295 | preempt_enable(); |
| 296 | } |
| 297 | |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 298 | void mips_cm_error_report(void) |
| 299 | { |
Paul Burton | 47b26a4 | 2015-09-22 10:26:41 -0700 | [diff] [blame] | 300 | u64 cm_error, cm_addr, cm_other; |
| 301 | unsigned long revision; |
| 302 | int ocause, cause; |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 303 | char buf[256]; |
| 304 | |
| 305 | if (!mips_cm_present()) |
| 306 | return; |
| 307 | |
Paul Burton | 03b1b85 | 2015-09-22 10:26:38 -0700 | [diff] [blame] | 308 | revision = mips_cm_revision(); |
Paul Burton | 03b1b85 | 2015-09-22 10:26:38 -0700 | [diff] [blame] | 309 | |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 310 | if (revision < CM_REV_CM3) { /* CM2 */ |
Paul Burton | 47b26a4 | 2015-09-22 10:26:41 -0700 | [diff] [blame] | 311 | cm_error = read_gcr_error_cause(); |
| 312 | cm_addr = read_gcr_error_addr(); |
| 313 | cm_other = read_gcr_error_mult(); |
| 314 | cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF; |
| 315 | ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF; |
| 316 | |
| 317 | if (!cause) |
| 318 | return; |
| 319 | |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 320 | if (cause < 16) { |
| 321 | unsigned long cca_bits = (cm_error >> 15) & 7; |
| 322 | unsigned long tr_bits = (cm_error >> 12) & 7; |
| 323 | unsigned long cmd_bits = (cm_error >> 7) & 0x1f; |
| 324 | unsigned long stag_bits = (cm_error >> 3) & 15; |
| 325 | unsigned long sport_bits = (cm_error >> 0) & 7; |
| 326 | |
| 327 | snprintf(buf, sizeof(buf), |
| 328 | "CCA=%lu TR=%s MCmd=%s STag=%lu " |
| 329 | "SPort=%lu\n", cca_bits, cm2_tr[tr_bits], |
| 330 | cm2_cmd[cmd_bits], stag_bits, sport_bits); |
| 331 | } else { |
| 332 | /* glob state & sresp together */ |
| 333 | unsigned long c3_bits = (cm_error >> 18) & 7; |
| 334 | unsigned long c2_bits = (cm_error >> 15) & 7; |
| 335 | unsigned long c1_bits = (cm_error >> 12) & 7; |
| 336 | unsigned long c0_bits = (cm_error >> 9) & 7; |
| 337 | unsigned long sc_bit = (cm_error >> 8) & 1; |
| 338 | unsigned long cmd_bits = (cm_error >> 3) & 0x1f; |
| 339 | unsigned long sport_bits = (cm_error >> 0) & 7; |
| 340 | |
| 341 | snprintf(buf, sizeof(buf), |
| 342 | "C3=%s C2=%s C1=%s C0=%s SC=%s " |
| 343 | "MCmd=%s SPort=%lu\n", |
| 344 | cm2_core[c3_bits], cm2_core[c2_bits], |
| 345 | cm2_core[c1_bits], cm2_core[c0_bits], |
| 346 | sc_bit ? "True" : "False", |
| 347 | cm2_cmd[cmd_bits], sport_bits); |
| 348 | } |
| 349 | pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error, |
| 350 | cm2_causes[cause], buf); |
Paul Burton | 47b26a4 | 2015-09-22 10:26:41 -0700 | [diff] [blame] | 351 | pr_err("CM_ADDR =%08llx\n", cm_addr); |
| 352 | pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]); |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 353 | } else { /* CM3 */ |
Paul Burton | 47b26a4 | 2015-09-22 10:26:41 -0700 | [diff] [blame] | 354 | ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits; |
| 355 | ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit; |
| 356 | |
| 357 | cm_error = read64_gcr_error_cause(); |
| 358 | cm_addr = read64_gcr_error_addr(); |
| 359 | cm_other = read64_gcr_error_mult(); |
| 360 | cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF; |
| 361 | ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF; |
| 362 | |
| 363 | if (!cause) |
| 364 | return; |
| 365 | |
| 366 | /* Used by cause == {1,2,3} */ |
| 367 | core_id_bits = (cm_error >> 22) & 0xf; |
| 368 | vp_id_bits = (cm_error >> 18) & 0xf; |
| 369 | cmd_bits = (cm_error >> 14) & 0xf; |
| 370 | cmd_group_bits = (cm_error >> 11) & 0xf; |
| 371 | cm3_cca_bits = (cm_error >> 8) & 7; |
| 372 | mcp_bits = (cm_error >> 5) & 0xf; |
| 373 | cm3_tr_bits = (cm_error >> 1) & 0xf; |
| 374 | sched_bit = cm_error & 0x1; |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 375 | |
| 376 | if (cause == 1 || cause == 3) { /* Tag ECC */ |
| 377 | unsigned long tag_ecc = (cm_error >> 57) & 0x1; |
| 378 | unsigned long tag_way_bits = (cm_error >> 29) & 0xffff; |
| 379 | unsigned long dword_bits = (cm_error >> 49) & 0xff; |
| 380 | unsigned long data_way_bits = (cm_error >> 45) & 0xf; |
| 381 | unsigned long data_sets_bits = (cm_error >> 29) & 0xfff; |
| 382 | unsigned long bank_bit = (cm_error >> 28) & 0x1; |
| 383 | snprintf(buf, sizeof(buf), |
| 384 | "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)" |
| 385 | "Bank=%lu CoreID=%lu VPID=%lu Command=%s" |
| 386 | "Command Group=%s CCA=%lu MCP=%d" |
| 387 | "Transaction type=%s Scheduler=%lu\n", |
| 388 | tag_ecc ? "TAG" : "DATA", |
| 389 | tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 : |
| 390 | data_way_bits, bank_bit, dword_bits, |
| 391 | data_sets_bits, |
| 392 | core_id_bits, vp_id_bits, |
| 393 | cm3_cmd[cmd_bits], |
| 394 | cm3_cmd_group[cmd_group_bits], |
| 395 | cm3_cca_bits, 1 << mcp_bits, |
| 396 | cm3_tr[cm3_tr_bits], sched_bit); |
| 397 | } else if (cause == 2) { |
| 398 | unsigned long data_error_type = (cm_error >> 41) & 0xfff; |
| 399 | unsigned long data_decode_cmd = (cm_error >> 37) & 0xf; |
| 400 | unsigned long data_decode_group = (cm_error >> 34) & 0x7; |
| 401 | unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f; |
| 402 | |
| 403 | snprintf(buf, sizeof(buf), |
| 404 | "Decode Request Error: Type=%lu, Command=%lu" |
| 405 | "Command Group=%lu Destination ID=%lu" |
| 406 | "CoreID=%lu VPID=%lu Command=%s" |
| 407 | "Command Group=%s CCA=%lu MCP=%d" |
| 408 | "Transaction type=%s Scheduler=%lu\n", |
| 409 | data_error_type, data_decode_cmd, |
| 410 | data_decode_group, data_decode_destination_id, |
| 411 | core_id_bits, vp_id_bits, |
| 412 | cm3_cmd[cmd_bits], |
| 413 | cm3_cmd_group[cmd_group_bits], |
| 414 | cm3_cca_bits, 1 << mcp_bits, |
| 415 | cm3_tr[cm3_tr_bits], sched_bit); |
Paul Burton | f88e632 | 2015-09-22 10:26:39 -0700 | [diff] [blame] | 416 | } else { |
| 417 | buf[0] = 0; |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | pr_err("CM_ERROR=%llx %s <%s>\n", cm_error, |
| 421 | cm3_causes[cause], buf); |
Paul Burton | 47b26a4 | 2015-09-22 10:26:41 -0700 | [diff] [blame] | 422 | pr_err("CM_ADDR =%llx\n", cm_addr); |
| 423 | pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]); |
Markos Chandras | 3885c2b | 2015-07-09 10:40:47 +0100 | [diff] [blame] | 424 | } |
| 425 | |
| 426 | /* reprime cause register */ |
| 427 | write_gcr_error_cause(0); |
| 428 | } |