File Index
Files and directories
Sign in
FILE

tegra234-cbb.c

File preview with syntax highlighting.

linux-6.19.14/drivers/soc/tegra/cbb/tegra234-cbb.c C
   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
  80enum 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
  92enum 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
 120enum 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
 129struct tegra234_target_lookup {
 130	const char *name;
 131	unsigned int offset;
 132};
 133
 134struct 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
 141struct 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
 156struct 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
 177static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb)
 178{
 179	return container_of(cbb, struct tegra234_cbb, base);
 180}
 181
 182static LIST_HEAD(cbb_list);
 183static DEFINE_SPINLOCK(cbb_lock);
 184
 185static bool
 186tegra234_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
 223static 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
 233static 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
 243static 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
 256static 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
 262static u32 tegra234_cbb_get_tmo_slv(void __iomem *addr)
 263{
 264	u32 timeout;
 265
 266	timeout = readl(addr);
 267	return timeout;
 268}
 269
 270static 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
 276static 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
 316static 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
 364static 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
 381static 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
 422static 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
 533static 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
 584static 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
 625static DEFINE_MUTEX(cbb_debugfs_mutex);
 626
 627static 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 */
 653static 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
 688unlock:
 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 */
 697static 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
 714static void tegra234_cbb_error_enable(struct tegra_cbb *cbb)
 715{
 716	tegra_cbb_fault_enable(cbb);
 717}
 718
 719static 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
 730static 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
 759static 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
 781static const struct tegra234_target_lookup tegra234_aon_target_map[] = {
 782	{ "AXI2APB", 0x00000 },
 783	{ "AST",     0x14000 },
 784	{ "CBB",     0x15000 },
 785	{ "CPU",     0x16000 },
 786};
 787
 788static 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
 796static 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
 805static 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
 869static 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
 892static 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
 906static 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
 920static 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
 935static 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
 949static 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
 963static 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
 977static 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 */
1007static 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
1086static 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
1097static 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
1159static 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};
1165static 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
1180static 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
1194static 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
1238static 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
1270static 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
1290static 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
1327static 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
1345static 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
1373static 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
1388static 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
1402static 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
1416static 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
1430static 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
1436static 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
1450static 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
1463static 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
1476static 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};
1489MODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids);
1490
1491struct tegra234_cbb_acpi_uid {
1492	const char *hid;
1493	const char *uid;
1494	const struct tegra234_cbb_fabric *fabric;
1495};
1496
1497static 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
1506static const struct
1507tegra234_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
1519static const struct acpi_device_id tegra241_cbb_acpi_ids[] = {
1520	{ "NVDA1070" },
1521	{ },
1522};
1523MODULE_DEVICE_TABLE(acpi, tegra241_cbb_acpi_ids);
1524
1525static 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
1585static 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
1596static const struct dev_pm_ops tegra234_cbb_pm = {
1597	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra234_cbb_resume_noirq)
1598};
1599
1600static 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
1610static int __init tegra234_cbb_init(void)
1611{
1612	return platform_driver_register(&tegra234_cbb_driver);
1613}
1614pure_initcall(tegra234_cbb_init);
1615
1616static void __exit tegra234_cbb_exit(void)
1617{
1618	platform_driver_unregister(&tegra234_cbb_driver);
1619}
1620module_exit(tegra234_cbb_exit);
1621
1622MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234");
~/ Read-only file preview.