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