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