xref: /linux/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c (revision fd7d598270724cc787982ea48bbe17ad383a8b7f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3  */
4 
5 #include <linux/bitops.h>
6 #include <linux/debugfs.h>
7 #include <linux/slab.h>
8 
9 #include "dpu_core_irq.h"
10 #include "dpu_kms.h"
11 #include "dpu_hw_interrupts.h"
12 #include "dpu_hw_util.h"
13 #include "dpu_hw_mdss.h"
14 #include "dpu_trace.h"
15 
16 /*
17  * Register offsets in MDSS register file for the interrupt registers
18  * w.r.t. the MDP base
19  */
20 #define MDP_INTF_OFF(intf)				(0x6A000 + 0x800 * (intf))
21 #define MDP_INTF_INTR_EN(intf)				(MDP_INTF_OFF(intf) + 0x1c0)
22 #define MDP_INTF_INTR_STATUS(intf)			(MDP_INTF_OFF(intf) + 0x1c4)
23 #define MDP_INTF_INTR_CLEAR(intf)			(MDP_INTF_OFF(intf) + 0x1c8)
24 #define MDP_INTF_TEAR_OFF(intf)				(0x6D700 + 0x100 * (intf))
25 #define MDP_INTF_INTR_TEAR_EN(intf)			(MDP_INTF_TEAR_OFF(intf) + 0x000)
26 #define MDP_INTF_INTR_TEAR_STATUS(intf)			(MDP_INTF_TEAR_OFF(intf) + 0x004)
27 #define MDP_INTF_INTR_TEAR_CLEAR(intf)			(MDP_INTF_TEAR_OFF(intf) + 0x008)
28 #define MDP_AD4_OFF(ad4)				(0x7C000 + 0x1000 * (ad4))
29 #define MDP_AD4_INTR_EN_OFF(ad4)			(MDP_AD4_OFF(ad4) + 0x41c)
30 #define MDP_AD4_INTR_CLEAR_OFF(ad4)			(MDP_AD4_OFF(ad4) + 0x424)
31 #define MDP_AD4_INTR_STATUS_OFF(ad4)			(MDP_AD4_OFF(ad4) + 0x420)
32 #define MDP_INTF_REV_7xxx_OFF(intf)			(0x34000 + 0x1000 * (intf))
33 #define MDP_INTF_REV_7xxx_INTR_EN(intf)			(MDP_INTF_REV_7xxx_OFF(intf) + 0x1c0)
34 #define MDP_INTF_REV_7xxx_INTR_STATUS(intf)		(MDP_INTF_REV_7xxx_OFF(intf) + 0x1c4)
35 #define MDP_INTF_REV_7xxx_INTR_CLEAR(intf)		(MDP_INTF_REV_7xxx_OFF(intf) + 0x1c8)
36 #define MDP_INTF_REV_7xxx_TEAR_OFF(intf)		(0x34800 + 0x1000 * (intf))
37 #define MDP_INTF_REV_7xxx_INTR_TEAR_EN(intf)		(MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x000)
38 #define MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(intf)	(MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x004)
39 #define MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(intf)		(MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x008)
40 
41 /**
42  * struct dpu_intr_reg - array of DPU register sets
43  * @clr_off:	offset to CLEAR reg
44  * @en_off:	offset to ENABLE reg
45  * @status_off:	offset to STATUS reg
46  */
47 struct dpu_intr_reg {
48 	u32 clr_off;
49 	u32 en_off;
50 	u32 status_off;
51 };
52 
53 /*
54  * dpu_intr_set_legacy -  List of DPU interrupt registers for DPU <= 6.x
55  */
56 static const struct dpu_intr_reg dpu_intr_set_legacy[] = {
57 	[MDP_SSPP_TOP0_INTR] = {
58 		INTR_CLEAR,
59 		INTR_EN,
60 		INTR_STATUS
61 	},
62 	[MDP_SSPP_TOP0_INTR2] = {
63 		INTR2_CLEAR,
64 		INTR2_EN,
65 		INTR2_STATUS
66 	},
67 	[MDP_SSPP_TOP0_HIST_INTR] = {
68 		HIST_INTR_CLEAR,
69 		HIST_INTR_EN,
70 		HIST_INTR_STATUS
71 	},
72 	[MDP_INTF0_INTR] = {
73 		MDP_INTF_INTR_CLEAR(0),
74 		MDP_INTF_INTR_EN(0),
75 		MDP_INTF_INTR_STATUS(0)
76 	},
77 	[MDP_INTF1_INTR] = {
78 		MDP_INTF_INTR_CLEAR(1),
79 		MDP_INTF_INTR_EN(1),
80 		MDP_INTF_INTR_STATUS(1)
81 	},
82 	[MDP_INTF2_INTR] = {
83 		MDP_INTF_INTR_CLEAR(2),
84 		MDP_INTF_INTR_EN(2),
85 		MDP_INTF_INTR_STATUS(2)
86 	},
87 	[MDP_INTF3_INTR] = {
88 		MDP_INTF_INTR_CLEAR(3),
89 		MDP_INTF_INTR_EN(3),
90 		MDP_INTF_INTR_STATUS(3)
91 	},
92 	[MDP_INTF4_INTR] = {
93 		MDP_INTF_INTR_CLEAR(4),
94 		MDP_INTF_INTR_EN(4),
95 		MDP_INTF_INTR_STATUS(4)
96 	},
97 	[MDP_INTF5_INTR] = {
98 		MDP_INTF_INTR_CLEAR(5),
99 		MDP_INTF_INTR_EN(5),
100 		MDP_INTF_INTR_STATUS(5)
101 	},
102 	[MDP_INTF1_TEAR_INTR] = {
103 		MDP_INTF_INTR_TEAR_CLEAR(1),
104 		MDP_INTF_INTR_TEAR_EN(1),
105 		MDP_INTF_INTR_TEAR_STATUS(1)
106 	},
107 	[MDP_INTF2_TEAR_INTR] = {
108 		MDP_INTF_INTR_TEAR_CLEAR(2),
109 		MDP_INTF_INTR_TEAR_EN(2),
110 		MDP_INTF_INTR_TEAR_STATUS(2)
111 	},
112 	[MDP_AD4_0_INTR] = {
113 		MDP_AD4_INTR_CLEAR_OFF(0),
114 		MDP_AD4_INTR_EN_OFF(0),
115 		MDP_AD4_INTR_STATUS_OFF(0),
116 	},
117 	[MDP_AD4_1_INTR] = {
118 		MDP_AD4_INTR_CLEAR_OFF(1),
119 		MDP_AD4_INTR_EN_OFF(1),
120 		MDP_AD4_INTR_STATUS_OFF(1),
121 	},
122 };
123 
124 /*
125  * dpu_intr_set_7xxx -  List of DPU interrupt registers for DPU >= 7.0
126  */
127 static const struct dpu_intr_reg dpu_intr_set_7xxx[] = {
128 	[MDP_SSPP_TOP0_INTR] = {
129 		INTR_CLEAR,
130 		INTR_EN,
131 		INTR_STATUS
132 	},
133 	[MDP_SSPP_TOP0_INTR2] = {
134 		INTR2_CLEAR,
135 		INTR2_EN,
136 		INTR2_STATUS
137 	},
138 	[MDP_SSPP_TOP0_HIST_INTR] = {
139 		HIST_INTR_CLEAR,
140 		HIST_INTR_EN,
141 		HIST_INTR_STATUS
142 	},
143 	[MDP_INTF0_INTR] = {
144 		MDP_INTF_REV_7xxx_INTR_CLEAR(0),
145 		MDP_INTF_REV_7xxx_INTR_EN(0),
146 		MDP_INTF_REV_7xxx_INTR_STATUS(0)
147 	},
148 	[MDP_INTF1_INTR] = {
149 		MDP_INTF_REV_7xxx_INTR_CLEAR(1),
150 		MDP_INTF_REV_7xxx_INTR_EN(1),
151 		MDP_INTF_REV_7xxx_INTR_STATUS(1)
152 	},
153 	[MDP_INTF1_TEAR_INTR] = {
154 		MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(1),
155 		MDP_INTF_REV_7xxx_INTR_TEAR_EN(1),
156 		MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(1)
157 	},
158 	[MDP_INTF2_INTR] = {
159 		MDP_INTF_REV_7xxx_INTR_CLEAR(2),
160 		MDP_INTF_REV_7xxx_INTR_EN(2),
161 		MDP_INTF_REV_7xxx_INTR_STATUS(2)
162 	},
163 	[MDP_INTF2_TEAR_INTR] = {
164 		MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(2),
165 		MDP_INTF_REV_7xxx_INTR_TEAR_EN(2),
166 		MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(2)
167 	},
168 	[MDP_INTF3_INTR] = {
169 		MDP_INTF_REV_7xxx_INTR_CLEAR(3),
170 		MDP_INTF_REV_7xxx_INTR_EN(3),
171 		MDP_INTF_REV_7xxx_INTR_STATUS(3)
172 	},
173 	[MDP_INTF4_INTR] = {
174 		MDP_INTF_REV_7xxx_INTR_CLEAR(4),
175 		MDP_INTF_REV_7xxx_INTR_EN(4),
176 		MDP_INTF_REV_7xxx_INTR_STATUS(4)
177 	},
178 	[MDP_INTF5_INTR] = {
179 		MDP_INTF_REV_7xxx_INTR_CLEAR(5),
180 		MDP_INTF_REV_7xxx_INTR_EN(5),
181 		MDP_INTF_REV_7xxx_INTR_STATUS(5)
182 	},
183 	[MDP_INTF6_INTR] = {
184 		MDP_INTF_REV_7xxx_INTR_CLEAR(6),
185 		MDP_INTF_REV_7xxx_INTR_EN(6),
186 		MDP_INTF_REV_7xxx_INTR_STATUS(6)
187 	},
188 	[MDP_INTF7_INTR] = {
189 		MDP_INTF_REV_7xxx_INTR_CLEAR(7),
190 		MDP_INTF_REV_7xxx_INTR_EN(7),
191 		MDP_INTF_REV_7xxx_INTR_STATUS(7)
192 	},
193 	[MDP_INTF8_INTR] = {
194 		MDP_INTF_REV_7xxx_INTR_CLEAR(8),
195 		MDP_INTF_REV_7xxx_INTR_EN(8),
196 		MDP_INTF_REV_7xxx_INTR_STATUS(8)
197 	},
198 };
199 
200 #define DPU_IRQ_MASK(irq_idx)	(BIT(DPU_IRQ_BIT(irq_idx)))
201 
202 static inline bool dpu_core_irq_is_valid(unsigned int irq_idx)
203 {
204 	return irq_idx && irq_idx <= DPU_NUM_IRQS;
205 }
206 
207 static inline struct dpu_hw_intr_entry *dpu_core_irq_get_entry(struct dpu_hw_intr *intr,
208 							       unsigned int irq_idx)
209 {
210 	return &intr->irq_tbl[irq_idx - 1];
211 }
212 
213 /**
214  * dpu_core_irq_callback_handler - dispatch core interrupts
215  * @dpu_kms:		Pointer to DPU's KMS structure
216  * @irq_idx:		interrupt index
217  */
218 static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, unsigned int irq_idx)
219 {
220 	struct dpu_hw_intr_entry *irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx);
221 
222 	VERB("IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
223 
224 	if (!irq_entry->cb)
225 		DRM_ERROR("no registered cb, IRQ=[%d, %d]\n",
226 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
227 
228 	atomic_inc(&irq_entry->count);
229 
230 	/*
231 	 * Perform registered function callback
232 	 */
233 	irq_entry->cb(irq_entry->arg);
234 }
235 
236 irqreturn_t dpu_core_irq(struct msm_kms *kms)
237 {
238 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
239 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
240 	int reg_idx;
241 	unsigned int irq_idx;
242 	u32 irq_status;
243 	u32 enable_mask;
244 	int bit;
245 	unsigned long irq_flags;
246 
247 	if (!intr)
248 		return IRQ_NONE;
249 
250 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
251 	for (reg_idx = 0; reg_idx < MDP_INTR_MAX; reg_idx++) {
252 		if (!test_bit(reg_idx, &intr->irq_mask))
253 			continue;
254 
255 		/* Read interrupt status */
256 		irq_status = DPU_REG_READ(&intr->hw, intr->intr_set[reg_idx].status_off);
257 
258 		/* Read enable mask */
259 		enable_mask = DPU_REG_READ(&intr->hw, intr->intr_set[reg_idx].en_off);
260 
261 		/* and clear the interrupt */
262 		if (irq_status)
263 			DPU_REG_WRITE(&intr->hw, intr->intr_set[reg_idx].clr_off,
264 				     irq_status);
265 
266 		/* Finally update IRQ status based on enable mask */
267 		irq_status &= enable_mask;
268 
269 		if (!irq_status)
270 			continue;
271 
272 		/*
273 		 * Search through matching intr status.
274 		 */
275 		while ((bit = ffs(irq_status)) != 0) {
276 			irq_idx = DPU_IRQ_IDX(reg_idx, bit - 1);
277 
278 			dpu_core_irq_callback_handler(dpu_kms, irq_idx);
279 
280 			/*
281 			 * When callback finish, clear the irq_status
282 			 * with the matching mask. Once irq_status
283 			 * is all cleared, the search can be stopped.
284 			 */
285 			irq_status &= ~BIT(bit - 1);
286 		}
287 	}
288 
289 	/* ensure register writes go through */
290 	wmb();
291 
292 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
293 
294 	return IRQ_HANDLED;
295 }
296 
297 static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr,
298 					 unsigned int irq_idx)
299 {
300 	int reg_idx;
301 	const struct dpu_intr_reg *reg;
302 	const char *dbgstr = NULL;
303 	uint32_t cache_irq_mask;
304 
305 	if (!intr)
306 		return -EINVAL;
307 
308 	if (!dpu_core_irq_is_valid(irq_idx)) {
309 		pr_err("invalid IRQ=[%d, %d]\n",
310 		       DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
311 		return -EINVAL;
312 	}
313 
314 	/*
315 	 * The cache_irq_mask and hardware RMW operations needs to be done
316 	 * under irq_lock and it's the caller's responsibility to ensure that's
317 	 * held.
318 	 */
319 	assert_spin_locked(&intr->irq_lock);
320 
321 	reg_idx = DPU_IRQ_REG(irq_idx);
322 	reg = &intr->intr_set[reg_idx];
323 
324 	/* Is this interrupt register supported on the platform */
325 	if (WARN_ON(!reg->en_off))
326 		return -EINVAL;
327 
328 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
329 	if (cache_irq_mask & DPU_IRQ_MASK(irq_idx)) {
330 		dbgstr = "already ";
331 	} else {
332 		dbgstr = "";
333 
334 		cache_irq_mask |= DPU_IRQ_MASK(irq_idx);
335 		/* Cleaning any pending interrupt */
336 		DPU_REG_WRITE(&intr->hw, reg->clr_off, DPU_IRQ_MASK(irq_idx));
337 		/* Enabling interrupts with the new mask */
338 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
339 
340 		/* ensure register write goes through */
341 		wmb();
342 
343 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
344 	}
345 
346 	pr_debug("DPU IRQ=[%d, %d] %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n",
347 		 DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr,
348 			DPU_IRQ_MASK(irq_idx), cache_irq_mask);
349 
350 	return 0;
351 }
352 
353 static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr,
354 					  unsigned int irq_idx)
355 {
356 	int reg_idx;
357 	const struct dpu_intr_reg *reg;
358 	const char *dbgstr = NULL;
359 	uint32_t cache_irq_mask;
360 
361 	if (!intr)
362 		return -EINVAL;
363 
364 	if (!dpu_core_irq_is_valid(irq_idx)) {
365 		pr_err("invalid IRQ=[%d, %d]\n",
366 		       DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
367 		return -EINVAL;
368 	}
369 
370 	/*
371 	 * The cache_irq_mask and hardware RMW operations needs to be done
372 	 * under irq_lock and it's the caller's responsibility to ensure that's
373 	 * held.
374 	 */
375 	assert_spin_locked(&intr->irq_lock);
376 
377 	reg_idx = DPU_IRQ_REG(irq_idx);
378 	reg = &intr->intr_set[reg_idx];
379 
380 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
381 	if ((cache_irq_mask & DPU_IRQ_MASK(irq_idx)) == 0) {
382 		dbgstr = "already ";
383 	} else {
384 		dbgstr = "";
385 
386 		cache_irq_mask &= ~DPU_IRQ_MASK(irq_idx);
387 		/* Disable interrupts based on the new mask */
388 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
389 		/* Cleaning any pending interrupt */
390 		DPU_REG_WRITE(&intr->hw, reg->clr_off, DPU_IRQ_MASK(irq_idx));
391 
392 		/* ensure register write goes through */
393 		wmb();
394 
395 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
396 	}
397 
398 	pr_debug("DPU IRQ=[%d, %d] %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n",
399 		 DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr,
400 			DPU_IRQ_MASK(irq_idx), cache_irq_mask);
401 
402 	return 0;
403 }
404 
405 static void dpu_clear_irqs(struct dpu_kms *dpu_kms)
406 {
407 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
408 	int i;
409 
410 	if (!intr)
411 		return;
412 
413 	for (i = 0; i < MDP_INTR_MAX; i++) {
414 		if (test_bit(i, &intr->irq_mask))
415 			DPU_REG_WRITE(&intr->hw,
416 					intr->intr_set[i].clr_off, 0xffffffff);
417 	}
418 
419 	/* ensure register writes go through */
420 	wmb();
421 }
422 
423 static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms)
424 {
425 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
426 	int i;
427 
428 	if (!intr)
429 		return;
430 
431 	for (i = 0; i < MDP_INTR_MAX; i++) {
432 		if (test_bit(i, &intr->irq_mask))
433 			DPU_REG_WRITE(&intr->hw,
434 					intr->intr_set[i].en_off, 0x00000000);
435 	}
436 
437 	/* ensure register writes go through */
438 	wmb();
439 }
440 
441 u32 dpu_core_irq_read(struct dpu_kms *dpu_kms,
442 		      unsigned int irq_idx)
443 {
444 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
445 	int reg_idx;
446 	unsigned long irq_flags;
447 	u32 intr_status;
448 
449 	if (!intr)
450 		return 0;
451 
452 	if (!dpu_core_irq_is_valid(irq_idx)) {
453 		pr_err("invalid IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
454 		return 0;
455 	}
456 
457 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
458 
459 	reg_idx = DPU_IRQ_REG(irq_idx);
460 	intr_status = DPU_REG_READ(&intr->hw,
461 			intr->intr_set[reg_idx].status_off) &
462 		DPU_IRQ_MASK(irq_idx);
463 	if (intr_status)
464 		DPU_REG_WRITE(&intr->hw, intr->intr_set[reg_idx].clr_off,
465 				intr_status);
466 
467 	/* ensure register writes go through */
468 	wmb();
469 
470 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
471 
472 	return intr_status;
473 }
474 
475 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
476 		const struct dpu_mdss_cfg *m)
477 {
478 	struct dpu_hw_intr *intr;
479 	unsigned int i;
480 
481 	if (!addr || !m)
482 		return ERR_PTR(-EINVAL);
483 
484 	intr = kzalloc(sizeof(*intr), GFP_KERNEL);
485 	if (!intr)
486 		return ERR_PTR(-ENOMEM);
487 
488 	if (m->mdss_ver->core_major_ver >= 7)
489 		intr->intr_set = dpu_intr_set_7xxx;
490 	else
491 		intr->intr_set = dpu_intr_set_legacy;
492 
493 	intr->hw.blk_addr = addr + m->mdp[0].base;
494 
495 	intr->irq_mask = BIT(MDP_SSPP_TOP0_INTR) |
496 			 BIT(MDP_SSPP_TOP0_INTR2) |
497 			 BIT(MDP_SSPP_TOP0_HIST_INTR);
498 	for (i = 0; i < m->intf_count; i++) {
499 		const struct dpu_intf_cfg *intf = &m->intf[i];
500 
501 		if (intf->type == INTF_NONE)
502 			continue;
503 
504 		intr->irq_mask |= BIT(MDP_INTFn_INTR(intf->id));
505 
506 		if (intf->intr_tear_rd_ptr)
507 			intr->irq_mask |= BIT(DPU_IRQ_REG(intf->intr_tear_rd_ptr));
508 	}
509 
510 	spin_lock_init(&intr->irq_lock);
511 
512 	return intr;
513 }
514 
515 void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
516 {
517 	kfree(intr);
518 }
519 
520 int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms,
521 				   unsigned int irq_idx,
522 				   void (*irq_cb)(void *arg),
523 				   void *irq_arg)
524 {
525 	struct dpu_hw_intr_entry *irq_entry;
526 	unsigned long irq_flags;
527 	int ret;
528 
529 	if (!irq_cb) {
530 		DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n",
531 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
532 		return -EINVAL;
533 	}
534 
535 	if (!dpu_core_irq_is_valid(irq_idx)) {
536 		DPU_ERROR("invalid IRQ=[%d, %d]\n",
537 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
538 		return -EINVAL;
539 	}
540 
541 	VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0),
542 	     DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
543 
544 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
545 
546 	irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx);
547 	if (unlikely(WARN_ON(irq_entry->cb))) {
548 		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
549 
550 		return -EBUSY;
551 	}
552 
553 	trace_dpu_core_irq_register_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
554 	irq_entry->arg = irq_arg;
555 	irq_entry->cb = irq_cb;
556 
557 	ret = dpu_hw_intr_enable_irq_locked(
558 				dpu_kms->hw_intr,
559 				irq_idx);
560 	if (ret)
561 		DPU_ERROR("Failed/ to enable IRQ=[%d, %d]\n",
562 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
563 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
564 
565 	trace_dpu_irq_register_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
566 
567 	return 0;
568 }
569 
570 int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms,
571 				     unsigned int irq_idx)
572 {
573 	struct dpu_hw_intr_entry *irq_entry;
574 	unsigned long irq_flags;
575 	int ret;
576 
577 	if (!dpu_core_irq_is_valid(irq_idx)) {
578 		DPU_ERROR("invalid IRQ=[%d, %d]\n",
579 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
580 		return -EINVAL;
581 	}
582 
583 	VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0),
584 	     DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
585 
586 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
587 	trace_dpu_core_irq_unregister_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
588 
589 	ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx);
590 	if (ret)
591 		DPU_ERROR("Failed to disable IRQ=[%d, %d]: %d\n",
592 			  DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), ret);
593 
594 	irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx);
595 	irq_entry->cb = NULL;
596 	irq_entry->arg = NULL;
597 
598 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
599 
600 	trace_dpu_irq_unregister_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
601 
602 	return 0;
603 }
604 
605 #ifdef CONFIG_DEBUG_FS
606 static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
607 {
608 	struct dpu_kms *dpu_kms = s->private;
609 	struct dpu_hw_intr_entry *irq_entry;
610 	unsigned long irq_flags;
611 	int i, irq_count;
612 	void *cb;
613 
614 	for (i = 1; i <= DPU_NUM_IRQS; i++) {
615 		spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
616 		irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i);
617 		irq_count = atomic_read(&irq_entry->count);
618 		cb = irq_entry->cb;
619 		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
620 
621 		if (irq_count || cb)
622 			seq_printf(s, "IRQ=[%d, %d] count:%d cb:%ps\n",
623 				   DPU_IRQ_REG(i), DPU_IRQ_BIT(i), irq_count, cb);
624 	}
625 
626 	return 0;
627 }
628 
629 DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq);
630 
631 void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
632 		struct dentry *parent)
633 {
634 	debugfs_create_file("core_irq", 0600, parent, dpu_kms,
635 		&dpu_debugfs_core_irq_fops);
636 }
637 #endif
638 
639 void dpu_core_irq_preinstall(struct msm_kms *kms)
640 {
641 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
642 	struct dpu_hw_intr_entry *irq_entry;
643 	int i;
644 
645 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
646 	dpu_clear_irqs(dpu_kms);
647 	dpu_disable_all_irqs(dpu_kms);
648 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
649 
650 	for (i = 1; i <= DPU_NUM_IRQS; i++) {
651 		irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i);
652 		atomic_set(&irq_entry->count, 0);
653 	}
654 }
655 
656 void dpu_core_irq_uninstall(struct msm_kms *kms)
657 {
658 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
659 	struct dpu_hw_intr_entry *irq_entry;
660 	int i;
661 
662 	if (!dpu_kms->hw_intr)
663 		return;
664 
665 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
666 	for (i = 1; i <= DPU_NUM_IRQS; i++) {
667 		irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i);
668 		if (irq_entry->cb)
669 			DPU_ERROR("IRQ=[%d, %d] still enabled/registered\n",
670 				  DPU_IRQ_REG(i), DPU_IRQ_BIT(i));
671 	}
672 
673 	dpu_clear_irqs(dpu_kms);
674 	dpu_disable_all_irqs(dpu_kms);
675 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
676 }
677