1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2021-2025, NVIDIA CORPORATION. All rights reserved 4 * 5 * The driver handles Error's from Control Backbone(CBB) version 2.0. 6 * generated due to illegal accesses. The driver prints debug information 7 * about failed transaction on receiving interrupt from Error Notifier. 8 * Error types supported by CBB2.0 are: 9 * UNSUPPORTED_ERR, PWRDOWN_ERR, TIMEOUT_ERR, FIREWALL_ERR, DECODE_ERR, 10 * TARGET_ERR 11 */ 12 13 #include <linux/acpi.h> 14 #include <linux/clk.h> 15 #include <linux/cpufeature.h> 16 #include <linux/debugfs.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 #include <linux/device.h> 21 #include <linux/io.h> 22 #include <linux/interrupt.h> 23 #include <linux/ioport.h> 24 #include <soc/tegra/fuse.h> 25 #include <soc/tegra/tegra-cbb.h> 26 27 #define FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0 0x0 28 #define FABRIC_EN_CFG_STATUS_0_0 0x40 29 #define FABRIC_EN_CFG_ADDR_INDEX_0_0 0x60 30 #define FABRIC_EN_CFG_ADDR_LOW_0 0x80 31 #define FABRIC_EN_CFG_ADDR_HI_0 0x84 32 33 #define FABRIC_EN_CFG_TARGET_NODE_ADDR_INDEX_0_0 0x100 34 #define FABRIC_EN_CFG_TARGET_NODE_ADDR_LOW_0 0x140 35 #define FABRIC_EN_CFG_TARGET_NODE_ADDR_HI_0 0x144 36 37 #define FABRIC_MN_INITIATOR_ERR_EN_0 0x200 38 #define FABRIC_MN_INITIATOR_ERR_FORCE_0 0x204 39 #define FABRIC_MN_INITIATOR_ERR_STATUS_0 0x208 40 #define FABRIC_MN_INITIATOR_ERR_OVERFLOW_STATUS_0 0x20c 41 42 #define FABRIC_MN_INITIATOR_LOG_ERR_STATUS_0 0x300 43 #define FABRIC_MN_INITIATOR_LOG_ADDR_LOW_0 0x304 44 #define FABRIC_MN_INITIATOR_LOG_ADDR_HIGH_0 0x308 45 #define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES0_0 0x30c 46 #define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES1_0 0x310 47 #define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES2_0 0x314 48 #define FABRIC_MN_INITIATOR_LOG_USER_BITS0_0 0x318 49 50 #define AXI_SLV_TIMEOUT_STATUS_0_0 0x8 51 #define APB_BLOCK_TMO_STATUS_0 0xc00 52 #define APB_BLOCK_NUM_TMO_OFFSET 0x20 53 54 #define FAB_EM_EL_MSTRID GENMASK(29, 24) 55 #define FAB_EM_EL_VQC GENMASK(17, 16) 56 #define FAB_EM_EL_GRPSEC GENMASK(14, 8) 57 #define FAB_EM_EL_FALCONSEC GENMASK(1, 0) 58 59 #define FAB_EM_EL_FABID GENMASK(20, 16) 60 #define FAB_EM_EL_TARGETID GENMASK(7, 0) 61 62 #define FAB_EM_EL_ACCESSID GENMASK(7, 0) 63 64 #define FAB_EM_EL_AXCACHE GENMASK(27, 24) 65 #define FAB_EM_EL_AXPROT GENMASK(22, 20) 66 #define FAB_EM_EL_BURSTLENGTH GENMASK(19, 12) 67 #define FAB_EM_EL_BURSTTYPE GENMASK(9, 8) 68 #define FAB_EM_EL_BEATSIZE GENMASK(6, 4) 69 #define FAB_EM_EL_ACCESSTYPE GENMASK(0, 0) 70 71 #define USRBITS_MSTR_ID GENMASK(29, 24) 72 73 #define REQ_SOCKET_ID GENMASK(27, 24) 74 75 #define CCPLEX_MSTRID 0x1 76 #define FIREWALL_APERTURE_SZ 0x10000 77 /* Write firewall check enable */ 78 #define WEN 0x20000 79 80 enum tegra234_cbb_fabric_ids { 81 T234_CBB_FABRIC_ID, 82 T234_SCE_FABRIC_ID, 83 T234_RCE_FABRIC_ID, 84 T234_DCE_FABRIC_ID, 85 T234_AON_FABRIC_ID, 86 T234_PSC_FABRIC_ID, 87 T234_BPMP_FABRIC_ID, 88 T234_FSI_FABRIC_ID, 89 T234_MAX_FABRIC_ID, 90 }; 91 92 enum tegra264_cbb_fabric_ids { 93 T264_SYSTEM_CBB_FABRIC_ID, 94 T264_TOP_0_CBB_FABRIC_ID, 95 T264_VISION_CBB_FABRIC_ID, 96 T264_DISP_USB_CBB_FABRIC_ID, 97 T264_UPHY0_CBB_FABRIC_ID, 98 T264_RSVD0_FABRIC_ID, 99 T264_RSVD1_FABRIC_ID, 100 T264_RSVD2_FABRIC_ID, 101 T264_RSVD3_FABRIC_ID, 102 T264_RSVD4_FABRIC_ID, 103 T264_RSVD5_FABRIC_ID, 104 T264_AON_FABRIC_ID, 105 T264_PSC_FABRIC_ID, 106 T264_OESP_FABRIC_ID, 107 T264_APE_FABRIC_ID, 108 T264_BPMP_FABRIC_ID, 109 T264_RCE_0_FABRIC_ID, 110 T264_RCE_1_FABRIC_ID, 111 T264_RSVD6_FABRIC_ID, 112 T264_DCE_FABRIC_ID, 113 T264_FSI_FABRIC_ID, 114 T264_ISC_FABRIC_ID, 115 T264_SB_FABRIC_ID, 116 T264_ISC_CPU_FABRIC_ID, 117 T264_RSVD7_FABRIC_ID, 118 }; 119 120 enum t254_cbb_fabric_ids { 121 T254_DCE_FABRIC_ID = 19, 122 T254_DISP_CLUSTER_FABRIC_ID = 25, 123 T254_C2C_FABRIC_ID = 26, 124 T254_GPU_FABRIC_ID = 27, 125 T254_DISP_CLUSTER_1_FABRIC_ID = 28, 126 T254_MAX_FABRIC_ID, 127 }; 128 129 struct tegra234_target_lookup { 130 const char *name; 131 unsigned int offset; 132 }; 133 134 struct tegra234_fabric_lookup { 135 const char *name; 136 bool is_lookup; 137 const struct tegra234_target_lookup *target_map; 138 const int max_targets; 139 }; 140 141 struct tegra234_cbb_fabric { 142 int fab_id; 143 phys_addr_t off_mask_erd; 144 phys_addr_t firewall_base; 145 unsigned int firewall_ctl; 146 unsigned int firewall_wr_ctl; 147 const char * const *initiator_id; 148 unsigned int notifier_offset; 149 const struct tegra_cbb_error *errors; 150 const int max_errors; 151 const struct tegra234_fabric_lookup *fab_list; 152 const u32 err_intr_enbl; 153 const u32 err_status_clr; 154 }; 155 156 struct tegra234_cbb { 157 struct tegra_cbb base; 158 159 const struct tegra234_cbb_fabric *fabric; 160 struct resource *res; 161 void __iomem *regs; 162 163 int num_intr; 164 int sec_irq; 165 166 /* record */ 167 void __iomem *mon; 168 unsigned int type; 169 u32 mask; 170 u64 access; 171 u32 mn_attr0; 172 u32 mn_attr1; 173 u32 mn_attr2; 174 u32 mn_user_bits; 175 }; 176 177 static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb) 178 { 179 return container_of(cbb, struct tegra234_cbb, base); 180 } 181 182 static LIST_HEAD(cbb_list); 183 static DEFINE_SPINLOCK(cbb_lock); 184 185 static bool 186 tegra234_cbb_write_access_allowed(struct platform_device *pdev, struct tegra234_cbb *cbb) 187 { 188 u32 val; 189 190 if (!cbb->fabric->firewall_base || 191 !cbb->fabric->firewall_ctl || 192 !cbb->fabric->firewall_wr_ctl) { 193 dev_info(&pdev->dev, "SoC data missing for firewall\n"); 194 return false; 195 } 196 197 if ((cbb->fabric->firewall_ctl > FIREWALL_APERTURE_SZ) || 198 (cbb->fabric->firewall_wr_ctl > FIREWALL_APERTURE_SZ)) { 199 dev_err(&pdev->dev, "wrong firewall offset value\n"); 200 return false; 201 } 202 203 val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_ctl); 204 /* 205 * If the firewall check feature for allowing or blocking the 206 * write accesses through the firewall of a fabric is disabled 207 * then CCPLEX can write to the registers of that fabric. 208 */ 209 if (!(val & WEN)) 210 return true; 211 212 /* 213 * If the firewall check is enabled then check whether CCPLEX 214 * has write access to the fabric's error notifier registers 215 */ 216 val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_wr_ctl); 217 if (val & (BIT(CCPLEX_MSTRID))) 218 return true; 219 220 return false; 221 } 222 223 static void tegra234_cbb_fault_enable(struct tegra_cbb *cbb) 224 { 225 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 226 void __iomem *addr; 227 228 addr = priv->regs + priv->fabric->notifier_offset; 229 writel(priv->fabric->err_intr_enbl, addr + FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0); 230 dsb(sy); 231 } 232 233 static void tegra234_cbb_error_clear(struct tegra_cbb *cbb) 234 { 235 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 236 237 writel(0, priv->mon + FABRIC_MN_INITIATOR_ERR_FORCE_0); 238 239 writel(priv->fabric->err_status_clr, priv->mon + FABRIC_MN_INITIATOR_ERR_STATUS_0); 240 dsb(sy); 241 } 242 243 static u32 tegra234_cbb_get_status(struct tegra_cbb *cbb) 244 { 245 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 246 void __iomem *addr; 247 u32 value; 248 249 addr = priv->regs + priv->fabric->notifier_offset; 250 value = readl(addr + FABRIC_EN_CFG_STATUS_0_0); 251 dsb(sy); 252 253 return value; 254 } 255 256 static void tegra234_cbb_mask_serror(struct tegra234_cbb *cbb) 257 { 258 writel(0x1, cbb->regs + cbb->fabric->off_mask_erd); 259 dsb(sy); 260 } 261 262 static u32 tegra234_cbb_get_tmo_slv(void __iomem *addr) 263 { 264 u32 timeout; 265 266 timeout = readl(addr); 267 return timeout; 268 } 269 270 static void tegra234_cbb_tmo_slv(struct seq_file *file, const char *target, void __iomem *addr, 271 u32 status) 272 { 273 tegra_cbb_print_err(file, "\t %s : %#x\n", target, status); 274 } 275 276 static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *target, 277 void __iomem *base) 278 { 279 unsigned int block = 0; 280 void __iomem *addr; 281 char name[64]; 282 u32 status; 283 284 status = tegra234_cbb_get_tmo_slv(base); 285 if (status) 286 tegra_cbb_print_err(file, "\t %s_BLOCK_TMO_STATUS : %#x\n", target, status); 287 288 while (status) { 289 if (status & BIT(0)) { 290 u32 timeout, clients, client = 0; 291 292 addr = base + APB_BLOCK_NUM_TMO_OFFSET + (block * 4); 293 timeout = tegra234_cbb_get_tmo_slv(addr); 294 clients = timeout; 295 296 while (timeout) { 297 if (timeout & BIT(0)) { 298 if (clients != 0xffffffff) 299 clients &= BIT(client); 300 301 sprintf(name, "%s_BLOCK%d_TMO", target, block); 302 303 tegra234_cbb_tmo_slv(file, name, addr, clients); 304 } 305 306 timeout >>= 1; 307 client++; 308 } 309 } 310 311 status >>= 1; 312 block++; 313 } 314 } 315 316 static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb, 317 u8 target_id, u8 fab_id) 318 { 319 const struct tegra234_target_lookup *map = cbb->fabric->fab_list[fab_id].target_map; 320 void __iomem *addr; 321 322 if (target_id >= cbb->fabric->fab_list[fab_id].max_targets) { 323 tegra_cbb_print_err(file, "\t Invalid target_id:%d\n", target_id); 324 return; 325 } 326 327 /* 328 * 1) Get target node name and address mapping using target_id. 329 * 2) Check if the timed out target node is APB or AXI. 330 * 3) If AXI, then print timeout register and reset axi target 331 * using <FABRIC>_SN_<>_SLV_TIMEOUT_STATUS_0_0 register. 332 * 4) If APB, then perform an additional lookup to find the client 333 * which timed out. 334 * a) Get block number from the index of set bit in 335 * <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. 336 * b) Get address of register respective to block number i.e. 337 * <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0. 338 * c) Read the register in above step to get client_id which 339 * timed out as per the set bits. 340 * d) Reset the timedout client and print details. 341 * e) Goto step-a till all bits are set. 342 */ 343 344 addr = cbb->regs + map[target_id].offset; 345 346 if (strstr(map[target_id].name, "AXI2APB")) { 347 addr += APB_BLOCK_TMO_STATUS_0; 348 349 tegra234_cbb_lookup_apbslv(file, map[target_id].name, addr); 350 } else { 351 char name[64]; 352 u32 status; 353 354 addr += AXI_SLV_TIMEOUT_STATUS_0_0; 355 356 status = tegra234_cbb_get_tmo_slv(addr); 357 if (status) { 358 sprintf(name, "%s_SLV_TIMEOUT_STATUS", map[target_id].name); 359 tegra234_cbb_tmo_slv(file, name, addr, status); 360 } 361 } 362 } 363 364 static void tegra234_hw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb, 365 u8 target_id, u8 fab_id) 366 { 367 unsigned int notifier = cbb->fabric->notifier_offset; 368 u32 hi, lo; 369 u64 addr; 370 371 writel(target_id, cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_INDEX_0_0); 372 373 hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_HI_0); 374 lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_LOW_0); 375 376 addr = (u64)hi << 32 | lo; 377 378 tegra_cbb_print_err(file, "\t Target Node Addr : %#llx\n", addr); 379 } 380 381 static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb *cbb, u32 status, 382 u32 overflow) 383 { 384 unsigned int type = 0; 385 386 if (status & (status - 1)) 387 tegra_cbb_print_err(file, "\t Multiple type of errors reported\n"); 388 389 while (status) { 390 if (type >= cbb->fabric->max_errors) { 391 tegra_cbb_print_err(file, "\t Wrong type index:%u, status:%u\n", 392 type, status); 393 return; 394 } 395 396 if (status & 0x1) 397 tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", 398 cbb->fabric->errors[type].code); 399 400 status >>= 1; 401 type++; 402 } 403 404 type = 0; 405 406 while (overflow) { 407 if (type >= cbb->fabric->max_errors) { 408 tegra_cbb_print_err(file, "\t Wrong type index:%u, overflow:%u\n", 409 type, overflow); 410 return; 411 } 412 413 if (overflow & 0x1) 414 tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n", 415 cbb->fabric->errors[type].code); 416 417 overflow >>= 1; 418 type++; 419 } 420 } 421 422 static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) 423 { 424 u8 cache_type, prot_type, burst_length, mstr_id, grpsec, vqc, falconsec, beat_size; 425 u8 access_type, access_id, requester_socket_id, local_socket_id, target_id, fab_id; 426 bool is_numa = false; 427 u8 burst_type; 428 429 if (num_possible_nodes() > 1) 430 is_numa = true; 431 432 mstr_id = FIELD_GET(FAB_EM_EL_MSTRID, cbb->mn_user_bits); 433 vqc = FIELD_GET(FAB_EM_EL_VQC, cbb->mn_user_bits); 434 grpsec = FIELD_GET(FAB_EM_EL_GRPSEC, cbb->mn_user_bits); 435 falconsec = FIELD_GET(FAB_EM_EL_FALCONSEC, cbb->mn_user_bits); 436 437 /* 438 * For SOC with multiple NUMA nodes, print cross socket access 439 * errors only if initiator_id is CCPLEX, CPMU or GPU. 440 */ 441 if (is_numa) { 442 local_socket_id = numa_node_id(); 443 requester_socket_id = FIELD_GET(REQ_SOCKET_ID, cbb->mn_attr2); 444 445 if (requester_socket_id != local_socket_id) { 446 if ((mstr_id != 0x1) && (mstr_id != 0x2) && (mstr_id != 0xB)) 447 return; 448 } 449 } 450 451 fab_id = FIELD_GET(FAB_EM_EL_FABID, cbb->mn_attr2); 452 target_id = FIELD_GET(FAB_EM_EL_TARGETID, cbb->mn_attr2); 453 454 access_id = FIELD_GET(FAB_EM_EL_ACCESSID, cbb->mn_attr1); 455 456 cache_type = FIELD_GET(FAB_EM_EL_AXCACHE, cbb->mn_attr0); 457 prot_type = FIELD_GET(FAB_EM_EL_AXPROT, cbb->mn_attr0); 458 burst_length = FIELD_GET(FAB_EM_EL_BURSTLENGTH, cbb->mn_attr0); 459 burst_type = FIELD_GET(FAB_EM_EL_BURSTTYPE, cbb->mn_attr0); 460 beat_size = FIELD_GET(FAB_EM_EL_BEATSIZE, cbb->mn_attr0); 461 access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0); 462 463 tegra_cbb_print_err(file, "\n"); 464 if (cbb->type < cbb->fabric->max_errors) 465 tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", 466 cbb->fabric->errors[cbb->type].code); 467 else 468 tegra_cbb_print_err(file, "\t Wrong type index:%u\n", cbb->type); 469 470 tegra_cbb_print_err(file, "\t Initiator_Id\t\t: %#x\n", mstr_id); 471 if (cbb->fabric->initiator_id) 472 tegra_cbb_print_err(file, "\t Initiator\t\t: %s\n", 473 cbb->fabric->initiator_id[mstr_id]); 474 475 tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access); 476 477 tegra_cbb_print_cache(file, cache_type); 478 tegra_cbb_print_prot(file, prot_type); 479 480 tegra_cbb_print_err(file, "\t Access_Type\t\t: %s", (access_type) ? "Write\n" : "Read\n"); 481 tegra_cbb_print_err(file, "\t Access_ID\t\t: %#x\n", access_id); 482 483 if (is_numa) { 484 tegra_cbb_print_err(file, "\t Requester_Socket_Id\t: %#x\n", 485 requester_socket_id); 486 tegra_cbb_print_err(file, "\t Local_Socket_Id\t: %#x\n", 487 local_socket_id); 488 tegra_cbb_print_err(file, "\t No. of NUMA_NODES\t: %#x\n", 489 num_possible_nodes()); 490 } 491 492 tegra_cbb_print_err(file, "\t Fabric\t\t: %s (id:%#x)\n", 493 cbb->fabric->fab_list[fab_id].name, fab_id); 494 495 if (of_machine_is_compatible("nvidia,tegra264") && fab_id == T264_UPHY0_CBB_FABRIC_ID) { 496 /* 497 * In T264, AON Fabric ID value is incorrectly same as UPHY0 fabric ID. 498 * For 'ID = 0x4', we must check for the address which caused the error 499 * to find the correct fabric which returned error. 500 */ 501 tegra_cbb_print_err(file, "\t or Fabric\t\t: %s\n", 502 cbb->fabric->fab_list[T264_AON_FABRIC_ID].name); 503 tegra_cbb_print_err(file, "\t Please use Address to determine correct fabric.\n"); 504 } 505 506 tegra_cbb_print_err(file, "\t Target_Id\t\t: %#x\n", target_id); 507 tegra_cbb_print_err(file, "\t Burst_length\t\t: %#x\n", burst_length); 508 tegra_cbb_print_err(file, "\t Burst_type\t\t: %#x\n", burst_type); 509 tegra_cbb_print_err(file, "\t Beat_size\t\t: %#x\n", beat_size); 510 tegra_cbb_print_err(file, "\t VQC\t\t\t: %#x\n", vqc); 511 tegra_cbb_print_err(file, "\t GRPSEC\t\t: %#x\n", grpsec); 512 tegra_cbb_print_err(file, "\t FALCONSEC\t\t: %#x\n", falconsec); 513 514 if (!cbb->fabric->fab_list[fab_id].is_lookup) 515 return; 516 517 /* 518 * If is_lookup field is set in fabric_lookup table of soc data, it 519 * means that address lookup of target is supported for Timeout errors. 520 * If is_lookup is set and the target_map is not populated making 521 * max_targets as zero, then it means HW lookup is to be performed. 522 */ 523 if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) { 524 if (cbb->fabric->fab_list[fab_id].max_targets) 525 tegra234_sw_lookup_target_timeout(file, cbb, target_id, fab_id); 526 else 527 tegra234_hw_lookup_target_timeout(file, cbb, target_id, fab_id); 528 } 529 530 return; 531 } 532 533 static int print_errmonX_info(struct seq_file *file, struct tegra234_cbb *cbb) 534 { 535 u32 overflow, status, error; 536 537 status = readl(cbb->mon + FABRIC_MN_INITIATOR_ERR_STATUS_0); 538 if (!status) { 539 pr_err("Error Notifier received a spurious notification\n"); 540 return -ENODATA; 541 } 542 543 if (status == 0xffffffff) { 544 pr_err("CBB registers returning all 1's which is invalid\n"); 545 return -EINVAL; 546 } 547 548 overflow = readl(cbb->mon + FABRIC_MN_INITIATOR_ERR_OVERFLOW_STATUS_0); 549 550 tegra234_cbb_print_error(file, cbb, status, overflow); 551 552 error = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ERR_STATUS_0); 553 if (!error) { 554 pr_info("Error Monitor doesn't have Error Logger\n"); 555 return -EINVAL; 556 } 557 558 cbb->type = 0; 559 560 while (error) { 561 if (error & BIT(0)) { 562 u32 hi, lo; 563 564 hi = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ADDR_HIGH_0); 565 lo = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ADDR_LOW_0); 566 567 cbb->access = (u64)hi << 32 | lo; 568 569 cbb->mn_attr0 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES0_0); 570 cbb->mn_attr1 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES1_0); 571 cbb->mn_attr2 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES2_0); 572 cbb->mn_user_bits = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_USER_BITS0_0); 573 574 print_errlog_err(file, cbb); 575 } 576 577 cbb->type++; 578 error >>= 1; 579 } 580 581 return 0; 582 } 583 584 static int print_err_notifier(struct seq_file *file, struct tegra234_cbb *cbb, u32 status) 585 { 586 unsigned int index = 0; 587 int err; 588 589 pr_crit("**************************************\n"); 590 pr_crit("CPU:%d, Error:%s, Errmon:%d\n", smp_processor_id(), 591 cbb->fabric->fab_list[cbb->fabric->fab_id].name, status); 592 593 while (status) { 594 if (status & BIT(0)) { 595 unsigned int notifier = cbb->fabric->notifier_offset; 596 u32 hi, lo, mask = BIT(index); 597 phys_addr_t addr; 598 u64 offset; 599 600 writel(mask, cbb->regs + notifier + FABRIC_EN_CFG_ADDR_INDEX_0_0); 601 hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_HI_0); 602 lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_LOW_0); 603 604 addr = (u64)hi << 32 | lo; 605 606 offset = addr - cbb->res->start; 607 cbb->mon = cbb->regs + offset; 608 cbb->mask = BIT(index); 609 610 err = print_errmonX_info(file, cbb); 611 tegra234_cbb_error_clear(&cbb->base); 612 if (err) 613 return err; 614 tegra_cbb_print_err(file, "\t**************************************\n"); 615 } 616 617 status >>= 1; 618 index++; 619 } 620 621 return 0; 622 } 623 624 #ifdef CONFIG_DEBUG_FS 625 static DEFINE_MUTEX(cbb_debugfs_mutex); 626 627 static int tegra234_cbb_debugfs_show(struct tegra_cbb *cbb, struct seq_file *file, void *data) 628 { 629 int err = 0; 630 631 mutex_lock(&cbb_debugfs_mutex); 632 633 list_for_each_entry(cbb, &cbb_list, node) { 634 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 635 u32 status; 636 637 status = tegra_cbb_get_status(&priv->base); 638 if (status) { 639 err = print_err_notifier(file, priv, status); 640 if (err) 641 break; 642 } 643 } 644 645 mutex_unlock(&cbb_debugfs_mutex); 646 return err; 647 } 648 #endif 649 650 /* 651 * Handler for CBB errors 652 */ 653 static irqreturn_t tegra234_cbb_isr(int irq, void *data) 654 { 655 bool is_inband_err = false; 656 struct tegra_cbb *cbb; 657 unsigned long flags; 658 u8 mstr_id; 659 int err; 660 661 spin_lock_irqsave(&cbb_lock, flags); 662 663 list_for_each_entry(cbb, &cbb_list, node) { 664 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 665 u32 status = tegra_cbb_get_status(cbb); 666 667 if (status && (irq == priv->sec_irq)) { 668 tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n", 669 smp_processor_id(), 670 priv->fabric->fab_list[priv->fabric->fab_id].name, 671 priv->res->start, irq); 672 673 err = print_err_notifier(NULL, priv, status); 674 if (err) 675 goto unlock; 676 677 /* 678 * If illegal request is from CCPLEX(id:0x1) initiator then call WARN() 679 */ 680 if (priv->fabric->off_mask_erd) { 681 mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); 682 if (mstr_id == CCPLEX_MSTRID) 683 is_inband_err = 1; 684 } 685 } 686 } 687 688 unlock: 689 spin_unlock_irqrestore(&cbb_lock, flags); 690 WARN_ON(is_inband_err); 691 return IRQ_HANDLED; 692 } 693 694 /* 695 * Register handler for CBB_SECURE interrupt for reporting errors 696 */ 697 static int tegra234_cbb_interrupt_enable(struct tegra_cbb *cbb) 698 { 699 struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 700 701 if (priv->sec_irq) { 702 int err = devm_request_irq(cbb->dev, priv->sec_irq, tegra234_cbb_isr, 0, 703 dev_name(cbb->dev), priv); 704 if (err) { 705 dev_err(cbb->dev, "failed to register interrupt %u: %d\n", priv->sec_irq, 706 err); 707 return err; 708 } 709 } 710 711 return 0; 712 } 713 714 static void tegra234_cbb_error_enable(struct tegra_cbb *cbb) 715 { 716 tegra_cbb_fault_enable(cbb); 717 } 718 719 static const struct tegra_cbb_ops tegra234_cbb_ops = { 720 .get_status = tegra234_cbb_get_status, 721 .error_clear = tegra234_cbb_error_clear, 722 .fault_enable = tegra234_cbb_fault_enable, 723 .error_enable = tegra234_cbb_error_enable, 724 .interrupt_enable = tegra234_cbb_interrupt_enable, 725 #ifdef CONFIG_DEBUG_FS 726 .debugfs_show = tegra234_cbb_debugfs_show, 727 #endif 728 }; 729 730 static const char * const tegra234_initiator_id[] = { 731 [0x00] = "TZ", 732 [0x01] = "CCPLEX", 733 [0x02] = "CCPMU", 734 [0x03] = "BPMP_FW", 735 [0x04] = "AON", 736 [0x05] = "SCE", 737 [0x06] = "GPCDMA_P", 738 [0x07] = "TSECA_NONSECURE", 739 [0x08] = "TSECA_LIGHTSECURE", 740 [0x09] = "TSECA_HEAVYSECURE", 741 [0x0a] = "CORESIGHT", 742 [0x0b] = "APE", 743 [0x0c] = "PEATRANS", 744 [0x0d] = "JTAGM_DFT", 745 [0x0e] = "RCE", 746 [0x0f] = "DCE", 747 [0x10] = "PSC_FW_USER", 748 [0x11] = "PSC_FW_SUPERVISOR", 749 [0x12] = "PSC_FW_MACHINE", 750 [0x13] = "PSC_BOOT", 751 [0x14] = "BPMP_BOOT", 752 [0x15] = "NVDEC_NONSECURE", 753 [0x16] = "NVDEC_LIGHTSECURE", 754 [0x17] = "NVDEC_HEAVYSECURE", 755 [0x18] = "CBB_INTERNAL", 756 [0x19] = "RSVD" 757 }; 758 759 static const struct tegra_cbb_error tegra234_cbb_errors[] = { 760 { 761 .code = "TARGET_ERR", 762 .desc = "Target being accessed responded with an error" 763 }, { 764 .code = "DECODE_ERR", 765 .desc = "Attempt to access an address hole" 766 }, { 767 .code = "FIREWALL_ERR", 768 .desc = "Attempt to access a region which is firewall protected" 769 }, { 770 .code = "TIMEOUT_ERR", 771 .desc = "No response returned by target" 772 }, { 773 .code = "PWRDOWN_ERR", 774 .desc = "Attempt to access a portion of fabric that is powered down" 775 }, { 776 .code = "UNSUPPORTED_ERR", 777 .desc = "Attempt to access a target through an unsupported access" 778 } 779 }; 780 781 static const struct tegra234_target_lookup tegra234_aon_target_map[] = { 782 { "AXI2APB", 0x00000 }, 783 { "AST", 0x14000 }, 784 { "CBB", 0x15000 }, 785 { "CPU", 0x16000 }, 786 }; 787 788 static const struct tegra234_target_lookup tegra234_bpmp_target_map[] = { 789 { "AXI2APB", 0x00000 }, 790 { "AST0", 0x15000 }, 791 { "AST1", 0x16000 }, 792 { "CBB", 0x17000 }, 793 { "CPU", 0x18000 }, 794 }; 795 796 static const struct tegra234_target_lookup tegra234_common_target_map[] = { 797 { "AXI2APB", 0x00000 }, 798 { "AST0", 0x15000 }, 799 { "AST1", 0x16000 }, 800 { "CBB", 0x17000 }, 801 { "RSVD", 0x00000 }, 802 { "CPU", 0x18000 }, 803 }; 804 805 static const struct tegra234_target_lookup tegra234_cbb_target_map[] = { 806 { "AON", 0x40000 }, 807 { "BPMP", 0x41000 }, 808 { "CBB", 0x42000 }, 809 { "HOST1X", 0x43000 }, 810 { "STM", 0x44000 }, 811 { "FSI", 0x45000 }, 812 { "PSC", 0x46000 }, 813 { "PCIE_C1", 0x47000 }, 814 { "PCIE_C2", 0x48000 }, 815 { "PCIE_C3", 0x49000 }, 816 { "PCIE_C0", 0x4a000 }, 817 { "PCIE_C4", 0x4b000 }, 818 { "GPU", 0x4c000 }, 819 { "SMMU0", 0x4d000 }, 820 { "SMMU1", 0x4e000 }, 821 { "SMMU2", 0x4f000 }, 822 { "SMMU3", 0x50000 }, 823 { "SMMU4", 0x51000 }, 824 { "PCIE_C10", 0x52000 }, 825 { "PCIE_C7", 0x53000 }, 826 { "PCIE_C8", 0x54000 }, 827 { "PCIE_C9", 0x55000 }, 828 { "PCIE_C5", 0x56000 }, 829 { "PCIE_C6", 0x57000 }, 830 { "DCE", 0x58000 }, 831 { "RCE", 0x59000 }, 832 { "SCE", 0x5a000 }, 833 { "AXI2APB_1", 0x70000 }, 834 { "AXI2APB_10", 0x71000 }, 835 { "AXI2APB_11", 0x72000 }, 836 { "AXI2APB_12", 0x73000 }, 837 { "AXI2APB_13", 0x74000 }, 838 { "AXI2APB_14", 0x75000 }, 839 { "AXI2APB_15", 0x76000 }, 840 { "AXI2APB_16", 0x77000 }, 841 { "AXI2APB_17", 0x78000 }, 842 { "AXI2APB_18", 0x79000 }, 843 { "AXI2APB_19", 0x7a000 }, 844 { "AXI2APB_2", 0x7b000 }, 845 { "AXI2APB_20", 0x7c000 }, 846 { "AXI2APB_21", 0x7d000 }, 847 { "AXI2APB_22", 0x7e000 }, 848 { "AXI2APB_23", 0x7f000 }, 849 { "AXI2APB_25", 0x80000 }, 850 { "AXI2APB_26", 0x81000 }, 851 { "AXI2APB_27", 0x82000 }, 852 { "AXI2APB_28", 0x83000 }, 853 { "AXI2APB_29", 0x84000 }, 854 { "AXI2APB_30", 0x85000 }, 855 { "AXI2APB_31", 0x86000 }, 856 { "AXI2APB_32", 0x87000 }, 857 { "AXI2APB_33", 0x88000 }, 858 { "AXI2APB_34", 0x89000 }, 859 { "AXI2APB_35", 0x92000 }, 860 { "AXI2APB_4", 0x8b000 }, 861 { "AXI2APB_5", 0x8c000 }, 862 { "AXI2APB_6", 0x8d000 }, 863 { "AXI2APB_7", 0x8e000 }, 864 { "AXI2APB_8", 0x8f000 }, 865 { "AXI2APB_9", 0x90000 }, 866 { "AXI2APB_3", 0x91000 }, 867 }; 868 869 static const struct tegra234_fabric_lookup tegra234_cbb_fab_list[] = { 870 [T234_CBB_FABRIC_ID] = { "cbb-fabric", true, 871 tegra234_cbb_target_map, 872 ARRAY_SIZE(tegra234_cbb_target_map) }, 873 [T234_SCE_FABRIC_ID] = { "sce-fabric", true, 874 tegra234_common_target_map, 875 ARRAY_SIZE(tegra234_common_target_map) }, 876 [T234_RCE_FABRIC_ID] = { "rce-fabric", true, 877 tegra234_common_target_map, 878 ARRAY_SIZE(tegra234_common_target_map) }, 879 [T234_DCE_FABRIC_ID] = { "dce-fabric", true, 880 tegra234_common_target_map, 881 ARRAY_SIZE(tegra234_common_target_map) }, 882 [T234_AON_FABRIC_ID] = { "aon-fabric", true, 883 tegra234_aon_target_map, 884 ARRAY_SIZE(tegra234_bpmp_target_map) }, 885 [T234_PSC_FABRIC_ID] = { "psc-fabric" }, 886 [T234_BPMP_FABRIC_ID] = { "bpmp-fabric", true, 887 tegra234_bpmp_target_map, 888 ARRAY_SIZE(tegra234_bpmp_target_map) }, 889 [T234_FSI_FABRIC_ID] = { "fsi-fabric" }, 890 }; 891 892 static const struct tegra234_cbb_fabric tegra234_aon_fabric = { 893 .fab_id = T234_AON_FABRIC_ID, 894 .fab_list = tegra234_cbb_fab_list, 895 .initiator_id = tegra234_initiator_id, 896 .errors = tegra234_cbb_errors, 897 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 898 .err_intr_enbl = 0x7, 899 .err_status_clr = 0x3f, 900 .notifier_offset = 0x17000, 901 .firewall_base = 0x30000, 902 .firewall_ctl = 0x8d0, 903 .firewall_wr_ctl = 0x8c8, 904 }; 905 906 static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = { 907 .fab_id = T234_BPMP_FABRIC_ID, 908 .fab_list = tegra234_cbb_fab_list, 909 .initiator_id = tegra234_initiator_id, 910 .errors = tegra234_cbb_errors, 911 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 912 .err_intr_enbl = 0xf, 913 .err_status_clr = 0x3f, 914 .notifier_offset = 0x19000, 915 .firewall_base = 0x30000, 916 .firewall_ctl = 0x8f0, 917 .firewall_wr_ctl = 0x8e8, 918 }; 919 920 static const struct tegra234_cbb_fabric tegra234_cbb_fabric = { 921 .fab_id = T234_CBB_FABRIC_ID, 922 .fab_list = tegra234_cbb_fab_list, 923 .initiator_id = tegra234_initiator_id, 924 .errors = tegra234_cbb_errors, 925 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 926 .err_intr_enbl = 0x7f, 927 .err_status_clr = 0x3f, 928 .notifier_offset = 0x60000, 929 .off_mask_erd = 0x3a004, 930 .firewall_base = 0x10000, 931 .firewall_ctl = 0x23f0, 932 .firewall_wr_ctl = 0x23e8, 933 }; 934 935 static const struct tegra234_cbb_fabric tegra234_dce_fabric = { 936 .fab_id = T234_DCE_FABRIC_ID, 937 .fab_list = tegra234_cbb_fab_list, 938 .initiator_id = tegra234_initiator_id, 939 .errors = tegra234_cbb_errors, 940 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 941 .err_intr_enbl = 0xf, 942 .err_status_clr = 0x3f, 943 .notifier_offset = 0x19000, 944 .firewall_base = 0x30000, 945 .firewall_ctl = 0x290, 946 .firewall_wr_ctl = 0x288, 947 }; 948 949 static const struct tegra234_cbb_fabric tegra234_rce_fabric = { 950 .fab_id = T234_RCE_FABRIC_ID, 951 .fab_list = tegra234_cbb_fab_list, 952 .initiator_id = tegra234_initiator_id, 953 .errors = tegra234_cbb_errors, 954 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 955 .err_intr_enbl = 0xf, 956 .err_status_clr = 0x3f, 957 .notifier_offset = 0x19000, 958 .firewall_base = 0x30000, 959 .firewall_ctl = 0x290, 960 .firewall_wr_ctl = 0x288, 961 }; 962 963 static const struct tegra234_cbb_fabric tegra234_sce_fabric = { 964 .fab_id = T234_SCE_FABRIC_ID, 965 .fab_list = tegra234_cbb_fab_list, 966 .initiator_id = tegra234_initiator_id, 967 .errors = tegra234_cbb_errors, 968 .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 969 .err_intr_enbl = 0xf, 970 .err_status_clr = 0x3f, 971 .notifier_offset = 0x19000, 972 .firewall_base = 0x30000, 973 .firewall_ctl = 0x290, 974 .firewall_wr_ctl = 0x288, 975 }; 976 977 static const char * const tegra241_initiator_id[] = { 978 [0x0] = "TZ", 979 [0x1] = "CCPLEX", 980 [0x2] = "CCPMU", 981 [0x3] = "BPMP_FW", 982 [0x4] = "PSC_FW_USER", 983 [0x5] = "PSC_FW_SUPERVISOR", 984 [0x6] = "PSC_FW_MACHINE", 985 [0x7] = "PSC_BOOT", 986 [0x8] = "BPMP_BOOT", 987 [0x9] = "JTAGM_DFT", 988 [0xa] = "CORESIGHT", 989 [0xb] = "GPU", 990 [0xc] = "PEATRANS", 991 [0xd ... 0x3f] = "RSVD" 992 }; 993 994 /* 995 * Possible causes for Target and Timeout errors. 996 * TARGET_ERR: 997 * Target being accessed responded with an error. Target could return 998 * an error for various cases : 999 * Unsupported access, clamp setting when power gated, register 1000 * level firewall(SCR), address hole within the target, etc 1001 * 1002 * TIMEOUT_ERR: 1003 * No response returned by target. Can be due to target being clock 1004 * gated, under reset, powered down or target inability to respond 1005 * for an internal target issue 1006 */ 1007 static const struct tegra_cbb_error tegra241_cbb_errors[] = { 1008 { 1009 .code = "TARGET_ERR", 1010 .desc = "Target being accessed responded with an error." 1011 }, { 1012 .code = "DECODE_ERR", 1013 .desc = "Attempt to access an address hole or Reserved region of memory." 1014 }, { 1015 .code = "FIREWALL_ERR", 1016 .desc = "Attempt to access a region which is firewalled." 1017 }, { 1018 .code = "TIMEOUT_ERR", 1019 .desc = "No response returned by target." 1020 }, { 1021 .code = "PWRDOWN_ERR", 1022 .desc = "Attempt to access a portion of the fabric that is powered down." 1023 }, { 1024 .code = "UNSUPPORTED_ERR", 1025 .desc = "Attempt to access a target through an unsupported access." 1026 }, { 1027 .code = "POISON_ERR", 1028 .desc = "Target responds with poison error to indicate error in data." 1029 }, { 1030 .code = "RSVD" 1031 }, { 1032 .code = "RSVD" 1033 }, { 1034 .code = "RSVD" 1035 }, { 1036 .code = "RSVD" 1037 }, { 1038 .code = "RSVD" 1039 }, { 1040 .code = "RSVD" 1041 }, { 1042 .code = "RSVD" 1043 }, { 1044 .code = "RSVD" 1045 }, { 1046 .code = "RSVD" 1047 }, { 1048 .code = "NO_SUCH_ADDRESS_ERR", 1049 .desc = "The address belongs to the pri_target range but there is no register " 1050 "implemented at the address." 1051 }, { 1052 .code = "TASK_ERR", 1053 .desc = "Attempt to update a PRI task when the current task has still not " 1054 "completed." 1055 }, { 1056 .code = "EXTERNAL_ERR", 1057 .desc = "Indicates that an external PRI register access met with an error due to " 1058 "any issue in the unit." 1059 }, { 1060 .code = "INDEX_ERR", 1061 .desc = "Applicable to PRI index aperture pair, when the programmed index is " 1062 "outside the range defined in the manual." 1063 }, { 1064 .code = "RESET_ERR", 1065 .desc = "Target in Reset Error: Attempt to access a SubPri or external PRI " 1066 "register but they are in reset." 1067 }, { 1068 .code = "REGISTER_RST_ERR", 1069 .desc = "Attempt to access a PRI register but the register is partial or " 1070 "completely in reset." 1071 }, { 1072 .code = "POWER_GATED_ERR", 1073 .desc = "Returned by external PRI client when the external access goes to a power " 1074 "gated domain." 1075 }, { 1076 .code = "SUBPRI_FS_ERR", 1077 .desc = "Subpri is floorswept: Attempt to access a subpri through the main pri " 1078 "target but subPri logic is floorswept." 1079 }, { 1080 .code = "SUBPRI_CLK_OFF_ERR", 1081 .desc = "Subpri clock is off: Attempt to access a subpri through the main pri " 1082 "target but subPris clock is gated/off." 1083 }, 1084 }; 1085 1086 static const struct tegra234_target_lookup tegra241_bpmp_target_map[] = { 1087 { "RSVD", 0x00000 }, 1088 { "RSVD", 0x00000 }, 1089 { "RSVD", 0x00000 }, 1090 { "CBB", 0x15000 }, 1091 { "CPU", 0x16000 }, 1092 { "AXI2APB", 0x00000 }, 1093 { "DBB0", 0x17000 }, 1094 { "DBB1", 0x18000 }, 1095 }; 1096 1097 static const struct tegra234_target_lookup tegra241_cbb_target_map[] = { 1098 { "RSVD", 0x00000 }, 1099 { "PCIE_C8", 0x51000 }, 1100 { "PCIE_C9", 0x52000 }, 1101 { "RSVD", 0x00000 }, 1102 { "RSVD", 0x00000 }, 1103 { "RSVD", 0x00000 }, 1104 { "RSVD", 0x00000 }, 1105 { "RSVD", 0x00000 }, 1106 { "RSVD", 0x00000 }, 1107 { "RSVD", 0x00000 }, 1108 { "RSVD", 0x00000 }, 1109 { "AON", 0x5b000 }, 1110 { "BPMP", 0x5c000 }, 1111 { "RSVD", 0x00000 }, 1112 { "RSVD", 0x00000 }, 1113 { "PSC", 0x5d000 }, 1114 { "STM", 0x5e000 }, 1115 { "AXI2APB_1", 0x70000 }, 1116 { "AXI2APB_10", 0x71000 }, 1117 { "AXI2APB_11", 0x72000 }, 1118 { "AXI2APB_12", 0x73000 }, 1119 { "AXI2APB_13", 0x74000 }, 1120 { "AXI2APB_14", 0x75000 }, 1121 { "AXI2APB_15", 0x76000 }, 1122 { "AXI2APB_16", 0x77000 }, 1123 { "AXI2APB_17", 0x78000 }, 1124 { "AXI2APB_18", 0x79000 }, 1125 { "AXI2APB_19", 0x7a000 }, 1126 { "AXI2APB_2", 0x7b000 }, 1127 { "AXI2APB_20", 0x7c000 }, 1128 { "AXI2APB_4", 0x87000 }, 1129 { "AXI2APB_5", 0x88000 }, 1130 { "AXI2APB_6", 0x89000 }, 1131 { "AXI2APB_7", 0x8a000 }, 1132 { "AXI2APB_8", 0x8b000 }, 1133 { "AXI2APB_9", 0x8c000 }, 1134 { "AXI2APB_3", 0x8d000 }, 1135 { "AXI2APB_21", 0x7d000 }, 1136 { "AXI2APB_22", 0x7e000 }, 1137 { "AXI2APB_23", 0x7f000 }, 1138 { "AXI2APB_24", 0x80000 }, 1139 { "AXI2APB_25", 0x81000 }, 1140 { "AXI2APB_26", 0x82000 }, 1141 { "AXI2APB_27", 0x83000 }, 1142 { "AXI2APB_28", 0x84000 }, 1143 { "PCIE_C4", 0x53000 }, 1144 { "PCIE_C5", 0x54000 }, 1145 { "PCIE_C6", 0x55000 }, 1146 { "PCIE_C7", 0x56000 }, 1147 { "PCIE_C2", 0x57000 }, 1148 { "PCIE_C3", 0x58000 }, 1149 { "PCIE_C0", 0x59000 }, 1150 { "PCIE_C1", 0x5a000 }, 1151 { "CCPLEX", 0x50000 }, 1152 { "AXI2APB_29", 0x85000 }, 1153 { "AXI2APB_30", 0x86000 }, 1154 { "CBB_CENTRAL", 0x00000 }, 1155 { "AXI2APB_31", 0x8E000 }, 1156 { "AXI2APB_32", 0x8F000 }, 1157 }; 1158 1159 static const struct tegra234_fabric_lookup tegra241_cbb_fab_list[] = { 1160 [T234_CBB_FABRIC_ID] = { "cbb-fabric", true, 1161 tegra241_cbb_target_map, ARRAY_SIZE(tegra241_cbb_target_map) }, 1162 [T234_BPMP_FABRIC_ID] = { "bpmp-fabric", true, 1163 tegra241_bpmp_target_map, ARRAY_SIZE(tegra241_cbb_target_map) }, 1164 }; 1165 static const struct tegra234_cbb_fabric tegra241_cbb_fabric = { 1166 .fab_id = T234_CBB_FABRIC_ID, 1167 .fab_list = tegra241_cbb_fab_list, 1168 .initiator_id = tegra241_initiator_id, 1169 .errors = tegra241_cbb_errors, 1170 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1171 .err_intr_enbl = 0x7, 1172 .err_status_clr = 0x1ff007f, 1173 .notifier_offset = 0x60000, 1174 .off_mask_erd = 0x40004, 1175 .firewall_base = 0x20000, 1176 .firewall_ctl = 0x2370, 1177 .firewall_wr_ctl = 0x2368, 1178 }; 1179 1180 static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = { 1181 .fab_id = T234_BPMP_FABRIC_ID, 1182 .fab_list = tegra241_cbb_fab_list, 1183 .initiator_id = tegra241_initiator_id, 1184 .errors = tegra241_cbb_errors, 1185 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1186 .err_intr_enbl = 0xf, 1187 .err_status_clr = 0x1ff007f, 1188 .notifier_offset = 0x19000, 1189 .firewall_base = 0x30000, 1190 .firewall_ctl = 0x8f0, 1191 .firewall_wr_ctl = 0x8e8, 1192 }; 1193 1194 static const char * const tegra264_initiator_id[] = { 1195 [0x0] = "TZ", 1196 [0x1] = "CCPLEX", 1197 [0x2] = "ISC", 1198 [0x3] = "BPMP_FW", 1199 [0x4] = "AON", 1200 [0x5] = "MSS_SEQ", 1201 [0x6] = "GPCDMA_P", 1202 [0x7] = "TSECA_NONSECURE", 1203 [0x8] = "TSECA_LIGHTSECURE", 1204 [0x9] = "TSECA_HEAVYSECURE", 1205 [0xa] = "CORESIGHT", 1206 [0xb] = "APE_0", 1207 [0xc] = "APE_1", 1208 [0xd] = "PEATRANS", 1209 [0xe] = "JTAGM_DFT", 1210 [0xf] = "RCE", 1211 [0x10] = "DCE", 1212 [0x11] = "PSC_FW_USER", 1213 [0x12] = "PSC_FW_SUPERVISOR", 1214 [0x13] = "PSC_FW_MACHINE", 1215 [0x14] = "PSC_BOOT", 1216 [0x15] = "BPMP_BOOT", 1217 [0x16] = "GPU_0", 1218 [0x17] = "GPU_1", 1219 [0x18] = "GPU_2", 1220 [0x19] = "GPU_3", 1221 [0x1a] = "GPU_4", 1222 [0x1b] = "PSC_EXT_BOOT", 1223 [0x1c] = "PSC_EXT_RUNTIME", 1224 [0x1d] = "OESP_EXT", 1225 [0x1e] = "SB_EXT", 1226 [0x1f] = "FSI_SAFETY_0", 1227 [0x20] = "FSI_SAFETY_1", 1228 [0x21] = "FSI_SAFETY_2", 1229 [0x22] = "FSI_SAFETY_3", 1230 [0x23] = "FSI_CHSM", 1231 [0x24] = "RCE_1", 1232 [0x25] = "BPMP_OEM_FW", 1233 [0x26 ... 0x3d] = "RSVD", 1234 [0x3e] = "CBB_SMN", 1235 [0x3f] = "CBB_RSVD" 1236 }; 1237 1238 static const struct tegra234_target_lookup tegra264_top0_cbb_target_map[] = { 1239 { "RSVD", 0x000000 }, 1240 { "CBB_CENTRAL", 0xC020000 }, 1241 { "AXI2APB_1", 0x80000 }, 1242 { "AXI2APB_10", 0x81000 }, 1243 { "AXI2APB_11", 0x82000 }, 1244 { "RSVD", 0x00000 }, 1245 { "RSVD", 0x00000 }, 1246 { "AXI2APB_14", 0x83000 }, 1247 { "AXI2APB_15", 0x84000 }, 1248 { "AXI2APB_16", 0x85000 }, 1249 { "AXI2APB_17", 0x86000 }, 1250 { "AXI2APB_2", 0x87000 }, 1251 { "AXI2APB_3", 0x88000 }, 1252 { "RSVD", 0x00000 }, 1253 { "AXI2APB_5", 0x8A000 }, 1254 { "AXI2APB_6", 0x8B000 }, 1255 { "AXI2APB_7", 0x8C000 }, 1256 { "AXI2APB_8", 0x8D000 }, 1257 { "AXI2APB_9", 0x8E000 }, 1258 { "FSI_SLAVE", 0x64000 }, 1259 { "DISP_USB_CBB_T", 0x65000 }, 1260 { "SYSTEM_CBB_T", 0x66000 }, 1261 { "UPHY0_CBB_T", 0x67000 }, 1262 { "VISION_CBB_T", 0x68000 }, 1263 { "CCPLEX_SLAVE", 0x69000 }, 1264 { "PCIE_C0", 0x6A000 }, 1265 { "SMN_UCF_RX_0", 0x6B000 }, 1266 { "SMN_UCF_RX_1", 0x6C000 }, 1267 { "AXI2APB_4", 0x89000 }, 1268 }; 1269 1270 static const struct tegra234_target_lookup tegra264_sys_cbb_target_map[] = { 1271 { "RSVD", 0x00000 }, 1272 { "AXI2APB_1", 0xE1000 }, 1273 { "RSVD", 0x00000 }, 1274 { "AON_SLAVE", 0x79000 }, 1275 { "APE_SLAVE", 0x73000 }, 1276 { "BPMP_SLAVE", 0x74000 }, 1277 { "OESP_SLAVE", 0x75000 }, 1278 { "PSC_SLAVE", 0x76000 }, 1279 { "SB_SLAVE", 0x7A000 }, 1280 { "SMN_SYSTEM_RX", 0x7B000 }, 1281 { "STM", 0x77000 }, 1282 { "RSVD", 0x00000 }, 1283 { "AXI2APB_3", 0xE3000 }, 1284 { "TOP_CBB_T", 0x7C000 }, 1285 { "AXI2APB_2", 0xE4000 }, 1286 { "AXI2APB_4", 0xE5000 }, 1287 { "AXI2APB_5", 0xE6000 }, 1288 }; 1289 1290 static const struct tegra234_target_lookup tegra264_uphy0_cbb_target_map[] = { 1291 [0 ... 20] = { "RSVD", 0x00000 }, 1292 { "AXI2APB_1", 0x71000 }, 1293 { "RSVD", 0x00000 }, 1294 { "AXI2APB_3", 0x75000 }, 1295 { "SMN_UPHY0_RX", 0x53000 }, 1296 { "RSVD", 0x00000 }, 1297 { "RSVD", 0x00000 }, 1298 { "RSVD", 0x00000 }, 1299 { "RSVD", 0x00000 }, 1300 { "PCIE_C4", 0x4B000 }, 1301 { "AXI2APB_2", 0x74000 }, 1302 { "AXI2APB_4", 0x76000 }, 1303 { "AXI2APB_5", 0x77000 }, 1304 { "RSVD", 0x00000 }, 1305 { "AXI2APB_7", 0x79000 }, 1306 { "PCIE_C2", 0x56000 }, 1307 { "RSVD", 0x00000 }, 1308 { "RSVD", 0x00000 }, 1309 { "PCIE_C1", 0x55000 }, 1310 { "RSVD", 0x00000 }, 1311 { "AXI2APB_10", 0x72000 }, 1312 { "AXI2APB_11", 0x7C000 }, 1313 { "AXI2APB_8", 0x7A000 }, 1314 { "AXI2APB_9", 0x7B000 }, 1315 { "RSVD", 0x00000 }, 1316 { "RSVD", 0x00000 }, 1317 { "PCIE_C5", 0x4E000 }, 1318 { "PCIE_C3", 0x58000 }, 1319 { "RSVD", 0x00000 }, 1320 { "ISC_SLAVE", 0x54000 }, 1321 { "TOP_CBB_T", 0x57000 }, 1322 { "AXI2APB_12", 0x7D000 }, 1323 { "AXI2APB_13", 0x70000 }, 1324 { "AXI2APB_6", 0x7E000 }, 1325 }; 1326 1327 static const struct tegra234_target_lookup tegra264_vision_cbb_target_map[] = { 1328 [0 ... 5] = { "RSVD", 0x0 }, 1329 { "HOST1X", 0x45000 }, 1330 { "RSVD", 0x00000 }, 1331 { "RSVD", 0x00000 }, 1332 { "AXI2APB_2", 0x71000 }, 1333 { "RSVD", 0x00000 }, 1334 { "RSVD", 0x00000 }, 1335 { "SMN_VISION_RX", 0x47000 }, 1336 [13 ... 19] = { "RSVD", 0x0 }, 1337 { "RCE_0_SLAVE", 0x4B000 }, 1338 { "RCE_1_SLAVE", 0x4C000 }, 1339 { "AXI2APB_1", 0x72000 }, 1340 { "AXI2APB_3", 0x73000 }, 1341 { "TOP_CBB_T", 0x4D000 }, 1342 1343 }; 1344 1345 static const struct tegra234_fabric_lookup tegra264_cbb_fab_list[] = { 1346 [T264_SYSTEM_CBB_FABRIC_ID] = { "system-cbb-fabric", true, 1347 tegra264_sys_cbb_target_map, 1348 ARRAY_SIZE(tegra264_sys_cbb_target_map) }, 1349 [T264_TOP_0_CBB_FABRIC_ID] = { "top0-cbb-fabric", true, 1350 tegra264_top0_cbb_target_map, 1351 ARRAY_SIZE(tegra264_top0_cbb_target_map) }, 1352 [T264_VISION_CBB_FABRIC_ID] = { "vision-cbb-fabric", true, 1353 tegra264_vision_cbb_target_map, 1354 ARRAY_SIZE(tegra264_vision_cbb_target_map) }, 1355 [T264_DISP_USB_CBB_FABRIC_ID] = { "disp-usb-cbb-fabric" }, 1356 [T264_UPHY0_CBB_FABRIC_ID] = { "uphy0-cbb-fabric", true, 1357 tegra264_uphy0_cbb_target_map, 1358 ARRAY_SIZE(tegra264_uphy0_cbb_target_map) }, 1359 [T264_AON_FABRIC_ID] = { "aon-fabric" }, 1360 [T264_PSC_FABRIC_ID] = { "psc-fabric" }, 1361 [T264_OESP_FABRIC_ID] = { "oesp-fabric" }, 1362 [T264_APE_FABRIC_ID] = { "ape-fabirc" }, 1363 [T264_BPMP_FABRIC_ID] = { "bpmp-fabric" }, 1364 [T264_RCE_0_FABRIC_ID] = { "rce0-fabric" }, 1365 [T264_RCE_1_FABRIC_ID] = { "rce1-fabric" }, 1366 [T264_DCE_FABRIC_ID] = { "dce-fabric" }, 1367 [T264_FSI_FABRIC_ID] = { "fsi-fabric" }, 1368 [T264_ISC_FABRIC_ID] = { "isc-fabric" }, 1369 [T264_SB_FABRIC_ID] = { "sb-fabric" }, 1370 [T264_ISC_CPU_FABRIC_ID] = { "isc-cpu-fabric" }, 1371 }; 1372 1373 static const struct tegra234_cbb_fabric tegra264_top0_cbb_fabric = { 1374 .fab_id = T264_TOP_0_CBB_FABRIC_ID, 1375 .fab_list = tegra264_cbb_fab_list, 1376 .initiator_id = tegra264_initiator_id, 1377 .errors = tegra241_cbb_errors, 1378 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1379 .err_intr_enbl = 0x7, 1380 .err_status_clr = 0x1ff007f, 1381 .notifier_offset = 0x90000, 1382 .off_mask_erd = 0x4a004, 1383 .firewall_base = 0x3c0000, 1384 .firewall_ctl = 0x5b0, 1385 .firewall_wr_ctl = 0x5a8, 1386 }; 1387 1388 static const struct tegra234_cbb_fabric tegra264_sys_cbb_fabric = { 1389 .fab_id = T264_SYSTEM_CBB_FABRIC_ID, 1390 .fab_list = tegra264_cbb_fab_list, 1391 .initiator_id = tegra264_initiator_id, 1392 .errors = tegra241_cbb_errors, 1393 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1394 .err_intr_enbl = 0xf, 1395 .err_status_clr = 0x1ff007f, 1396 .notifier_offset = 0x40000, 1397 .firewall_base = 0x29c000, 1398 .firewall_ctl = 0x170, 1399 .firewall_wr_ctl = 0x168, 1400 }; 1401 1402 static const struct tegra234_cbb_fabric tegra264_uphy0_cbb_fabric = { 1403 .fab_id = T264_UPHY0_CBB_FABRIC_ID, 1404 .fab_list = tegra264_cbb_fab_list, 1405 .initiator_id = tegra264_initiator_id, 1406 .errors = tegra241_cbb_errors, 1407 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1408 .err_intr_enbl = 0x1, 1409 .err_status_clr = 0x1ff007f, 1410 .notifier_offset = 0x80000, 1411 .firewall_base = 0x360000, 1412 .firewall_ctl = 0x590, 1413 .firewall_wr_ctl = 0x588, 1414 }; 1415 1416 static const struct tegra234_cbb_fabric tegra264_vision_cbb_fabric = { 1417 .fab_id = T264_VISION_CBB_FABRIC_ID, 1418 .fab_list = tegra264_cbb_fab_list, 1419 .initiator_id = tegra264_initiator_id, 1420 .errors = tegra241_cbb_errors, 1421 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1422 .err_intr_enbl = 0x1, 1423 .err_status_clr = 0x1ff007f, 1424 .notifier_offset = 0x80000, 1425 .firewall_base = 0x290000, 1426 .firewall_ctl = 0x5d0, 1427 .firewall_wr_ctl = 0x5c8, 1428 }; 1429 1430 static const struct tegra234_fabric_lookup t254_cbb_fab_list[] = { 1431 [T254_C2C_FABRIC_ID] = { "c2c-fabric", true }, 1432 [T254_DISP_CLUSTER_FABRIC_ID] = { "display-cluster-fabric", true }, 1433 [T254_GPU_FABRIC_ID] = { "gpu-fabric", true }, 1434 }; 1435 1436 static const struct tegra234_cbb_fabric t254_c2c_fabric = { 1437 .fab_id = T254_C2C_FABRIC_ID, 1438 .fab_list = t254_cbb_fab_list, 1439 .errors = tegra241_cbb_errors, 1440 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1441 .err_intr_enbl = 0xf, 1442 .err_status_clr = 0x1ff007f, 1443 .notifier_offset = 0x50000, 1444 .off_mask_erd = 0x14004, 1445 .firewall_base = 0x40000, 1446 .firewall_ctl = 0x9b0, 1447 .firewall_wr_ctl = 0x9a8, 1448 }; 1449 1450 static const struct tegra234_cbb_fabric t254_disp_fabric = { 1451 .fab_id = T254_DISP_CLUSTER_FABRIC_ID, 1452 .fab_list = t254_cbb_fab_list, 1453 .errors = tegra241_cbb_errors, 1454 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1455 .err_intr_enbl = 0x1, 1456 .err_status_clr = 0x1ff007f, 1457 .notifier_offset = 0x50000, 1458 .firewall_base = 0x30000, 1459 .firewall_ctl = 0x810, 1460 .firewall_wr_ctl = 0x808, 1461 }; 1462 1463 static const struct tegra234_cbb_fabric t254_gpu_fabric = { 1464 .fab_id = T254_GPU_FABRIC_ID, 1465 .fab_list = t254_cbb_fab_list, 1466 .errors = tegra241_cbb_errors, 1467 .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 1468 .err_intr_enbl = 0x1f, 1469 .err_status_clr = 0x1ff007f, 1470 .notifier_offset = 0x50000, 1471 .firewall_base = 0x30000, 1472 .firewall_ctl = 0x930, 1473 .firewall_wr_ctl = 0x928, 1474 }; 1475 1476 static const struct of_device_id tegra234_cbb_dt_ids[] = { 1477 { .compatible = "nvidia,tegra234-cbb-fabric", .data = &tegra234_cbb_fabric }, 1478 { .compatible = "nvidia,tegra234-aon-fabric", .data = &tegra234_aon_fabric }, 1479 { .compatible = "nvidia,tegra234-bpmp-fabric", .data = &tegra234_bpmp_fabric }, 1480 { .compatible = "nvidia,tegra234-dce-fabric", .data = &tegra234_dce_fabric }, 1481 { .compatible = "nvidia,tegra234-rce-fabric", .data = &tegra234_rce_fabric }, 1482 { .compatible = "nvidia,tegra234-sce-fabric", .data = &tegra234_sce_fabric }, 1483 { .compatible = "nvidia,tegra264-sys-cbb-fabric", .data = &tegra264_sys_cbb_fabric }, 1484 { .compatible = "nvidia,tegra264-top0-cbb-fabric", .data = &tegra264_top0_cbb_fabric }, 1485 { .compatible = "nvidia,tegra264-uphy0-cbb-fabric", .data = &tegra264_uphy0_cbb_fabric }, 1486 { .compatible = "nvidia,tegra264-vision-cbb-fabric", .data = &tegra264_vision_cbb_fabric }, 1487 { /* sentinel */ }, 1488 }; 1489 MODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids); 1490 1491 struct tegra234_cbb_acpi_uid { 1492 const char *hid; 1493 const char *uid; 1494 const struct tegra234_cbb_fabric *fabric; 1495 }; 1496 1497 static const struct tegra234_cbb_acpi_uid tegra234_cbb_acpi_uids[] = { 1498 { "NVDA1070", "1", &tegra241_cbb_fabric }, 1499 { "NVDA1070", "2", &tegra241_bpmp_fabric }, 1500 { "NVDA1070", "3", &t254_c2c_fabric }, 1501 { "NVDA1070", "4", &t254_disp_fabric }, 1502 { "NVDA1070", "5", &t254_gpu_fabric }, 1503 { }, 1504 }; 1505 1506 static const struct 1507 tegra234_cbb_fabric *tegra234_cbb_acpi_get_fabric(struct acpi_device *adev) 1508 { 1509 const struct tegra234_cbb_acpi_uid *entry; 1510 1511 for (entry = tegra234_cbb_acpi_uids; entry->hid; entry++) { 1512 if (acpi_dev_hid_uid_match(adev, entry->hid, entry->uid)) 1513 return entry->fabric; 1514 } 1515 1516 return NULL; 1517 } 1518 1519 static const struct acpi_device_id tegra241_cbb_acpi_ids[] = { 1520 { "NVDA1070" }, 1521 { }, 1522 }; 1523 MODULE_DEVICE_TABLE(acpi, tegra241_cbb_acpi_ids); 1524 1525 static int tegra234_cbb_probe(struct platform_device *pdev) 1526 { 1527 const struct tegra234_cbb_fabric *fabric; 1528 struct tegra234_cbb *cbb; 1529 unsigned long flags = 0; 1530 int err; 1531 1532 if (pdev->dev.of_node) { 1533 fabric = of_device_get_match_data(&pdev->dev); 1534 } else { 1535 struct acpi_device *device = ACPI_COMPANION(&pdev->dev); 1536 if (!device) 1537 return -ENODEV; 1538 1539 fabric = tegra234_cbb_acpi_get_fabric(device); 1540 if (!fabric) { 1541 dev_err(&pdev->dev, "no device match found\n"); 1542 return -ENODEV; 1543 } 1544 } 1545 1546 cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL); 1547 if (!cbb) 1548 return -ENOMEM; 1549 1550 INIT_LIST_HEAD(&cbb->base.node); 1551 cbb->base.ops = &tegra234_cbb_ops; 1552 cbb->base.dev = &pdev->dev; 1553 cbb->fabric = fabric; 1554 1555 cbb->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &cbb->res); 1556 if (IS_ERR(cbb->regs)) 1557 return PTR_ERR(cbb->regs); 1558 1559 err = tegra_cbb_get_irq(pdev, NULL, &cbb->sec_irq); 1560 if (err) 1561 return err; 1562 1563 platform_set_drvdata(pdev, cbb); 1564 1565 /* 1566 * Don't enable error reporting for a Fabric if write to it's registers 1567 * is blocked by CBB firewall. 1568 */ 1569 if (!tegra234_cbb_write_access_allowed(pdev, cbb)) { 1570 dev_info(&pdev->dev, "error reporting not enabled due to firewall\n"); 1571 return 0; 1572 } 1573 1574 spin_lock_irqsave(&cbb_lock, flags); 1575 list_add(&cbb->base.node, &cbb_list); 1576 spin_unlock_irqrestore(&cbb_lock, flags); 1577 1578 /* set ERD bit to mask SError and generate interrupt to report error */ 1579 if (cbb->fabric->off_mask_erd) 1580 tegra234_cbb_mask_serror(cbb); 1581 1582 return tegra_cbb_register(&cbb->base); 1583 } 1584 1585 static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev) 1586 { 1587 struct tegra234_cbb *cbb = dev_get_drvdata(dev); 1588 1589 tegra234_cbb_error_enable(&cbb->base); 1590 1591 dev_dbg(dev, "%s resumed\n", cbb->fabric->fab_list[cbb->fabric->fab_id].name); 1592 1593 return 0; 1594 } 1595 1596 static const struct dev_pm_ops tegra234_cbb_pm = { 1597 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra234_cbb_resume_noirq) 1598 }; 1599 1600 static struct platform_driver tegra234_cbb_driver = { 1601 .probe = tegra234_cbb_probe, 1602 .driver = { 1603 .name = "tegra234-cbb", 1604 .of_match_table = tegra234_cbb_dt_ids, 1605 .acpi_match_table = tegra241_cbb_acpi_ids, 1606 .pm = &tegra234_cbb_pm, 1607 }, 1608 }; 1609 1610 static int __init tegra234_cbb_init(void) 1611 { 1612 return platform_driver_register(&tegra234_cbb_driver); 1613 } 1614 pure_initcall(tegra234_cbb_init); 1615 1616 static void __exit tegra234_cbb_exit(void) 1617 { 1618 platform_driver_unregister(&tegra234_cbb_driver); 1619 } 1620 module_exit(tegra234_cbb_exit); 1621 1622 MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234"); 1623