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