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_SSPP_TOP0_OFF		0x0
21 #define MDP_INTF_0_OFF			0x6A000
22 #define MDP_INTF_1_OFF			0x6A800
23 #define MDP_INTF_2_OFF			0x6B000
24 #define MDP_INTF_3_OFF			0x6B800
25 #define MDP_INTF_4_OFF			0x6C000
26 #define MDP_INTF_5_OFF			0x6C800
27 #define INTF_INTR_EN			0x1c0
28 #define INTF_INTR_STATUS		0x1c4
29 #define INTF_INTR_CLEAR			0x1c8
30 #define MDP_AD4_0_OFF			0x7C000
31 #define MDP_AD4_1_OFF			0x7D000
32 #define MDP_AD4_INTR_EN_OFF		0x41c
33 #define MDP_AD4_INTR_CLEAR_OFF		0x424
34 #define MDP_AD4_INTR_STATUS_OFF		0x420
35 #define MDP_INTF_0_OFF_REV_7xxx		0x34000
36 #define MDP_INTF_1_OFF_REV_7xxx		0x35000
37 #define MDP_INTF_2_OFF_REV_7xxx		0x36000
38 #define MDP_INTF_3_OFF_REV_7xxx		0x37000
39 #define MDP_INTF_4_OFF_REV_7xxx		0x38000
40 #define MDP_INTF_5_OFF_REV_7xxx		0x39000
41 #define MDP_INTF_6_OFF_REV_7xxx		0x3a000
42 #define MDP_INTF_7_OFF_REV_7xxx		0x3b000
43 #define MDP_INTF_8_OFF_REV_7xxx		0x3c000
44 
45 /**
46  * struct dpu_intr_reg - array of DPU register sets
47  * @clr_off:	offset to CLEAR reg
48  * @en_off:	offset to ENABLE reg
49  * @status_off:	offset to STATUS reg
50  */
51 struct dpu_intr_reg {
52 	u32 clr_off;
53 	u32 en_off;
54 	u32 status_off;
55 };
56 
57 /*
58  * struct dpu_intr_reg -  List of DPU interrupt registers
59  *
60  * When making changes be sure to sync with dpu_hw_intr_reg
61  */
62 static const struct dpu_intr_reg dpu_intr_set[] = {
63 	[MDP_SSPP_TOP0_INTR] = {
64 		MDP_SSPP_TOP0_OFF+INTR_CLEAR,
65 		MDP_SSPP_TOP0_OFF+INTR_EN,
66 		MDP_SSPP_TOP0_OFF+INTR_STATUS
67 	},
68 	[MDP_SSPP_TOP0_INTR2] = {
69 		MDP_SSPP_TOP0_OFF+INTR2_CLEAR,
70 		MDP_SSPP_TOP0_OFF+INTR2_EN,
71 		MDP_SSPP_TOP0_OFF+INTR2_STATUS
72 	},
73 	[MDP_SSPP_TOP0_HIST_INTR] = {
74 		MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR,
75 		MDP_SSPP_TOP0_OFF+HIST_INTR_EN,
76 		MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS
77 	},
78 	[MDP_INTF0_INTR] = {
79 		MDP_INTF_0_OFF+INTF_INTR_CLEAR,
80 		MDP_INTF_0_OFF+INTF_INTR_EN,
81 		MDP_INTF_0_OFF+INTF_INTR_STATUS
82 	},
83 	[MDP_INTF1_INTR] = {
84 		MDP_INTF_1_OFF+INTF_INTR_CLEAR,
85 		MDP_INTF_1_OFF+INTF_INTR_EN,
86 		MDP_INTF_1_OFF+INTF_INTR_STATUS
87 	},
88 	[MDP_INTF2_INTR] = {
89 		MDP_INTF_2_OFF+INTF_INTR_CLEAR,
90 		MDP_INTF_2_OFF+INTF_INTR_EN,
91 		MDP_INTF_2_OFF+INTF_INTR_STATUS
92 	},
93 	[MDP_INTF3_INTR] = {
94 		MDP_INTF_3_OFF+INTF_INTR_CLEAR,
95 		MDP_INTF_3_OFF+INTF_INTR_EN,
96 		MDP_INTF_3_OFF+INTF_INTR_STATUS
97 	},
98 	[MDP_INTF4_INTR] = {
99 		MDP_INTF_4_OFF+INTF_INTR_CLEAR,
100 		MDP_INTF_4_OFF+INTF_INTR_EN,
101 		MDP_INTF_4_OFF+INTF_INTR_STATUS
102 	},
103 	[MDP_INTF5_INTR] = {
104 		MDP_INTF_5_OFF+INTF_INTR_CLEAR,
105 		MDP_INTF_5_OFF+INTF_INTR_EN,
106 		MDP_INTF_5_OFF+INTF_INTR_STATUS
107 	},
108 	[MDP_AD4_0_INTR] = {
109 		MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF,
110 		MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF,
111 		MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF,
112 	},
113 	[MDP_AD4_1_INTR] = {
114 		MDP_AD4_1_OFF + MDP_AD4_INTR_CLEAR_OFF,
115 		MDP_AD4_1_OFF + MDP_AD4_INTR_EN_OFF,
116 		MDP_AD4_1_OFF + MDP_AD4_INTR_STATUS_OFF,
117 	},
118 	[MDP_INTF0_7xxx_INTR] = {
119 		MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_CLEAR,
120 		MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_EN,
121 		MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_STATUS
122 	},
123 	[MDP_INTF1_7xxx_INTR] = {
124 		MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_CLEAR,
125 		MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_EN,
126 		MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS
127 	},
128 	[MDP_INTF2_7xxx_INTR] = {
129 		MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR,
130 		MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN,
131 		MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS
132 	},
133 	[MDP_INTF3_7xxx_INTR] = {
134 		MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR,
135 		MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN,
136 		MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS
137 	},
138 	[MDP_INTF4_7xxx_INTR] = {
139 		MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR,
140 		MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN,
141 		MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS
142 	},
143 	[MDP_INTF5_7xxx_INTR] = {
144 		MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR,
145 		MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN,
146 		MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_STATUS
147 	},
148 	[MDP_INTF6_7xxx_INTR] = {
149 		MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_CLEAR,
150 		MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_EN,
151 		MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_STATUS
152 	},
153 	[MDP_INTF7_7xxx_INTR] = {
154 		MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_CLEAR,
155 		MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_EN,
156 		MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_STATUS
157 	},
158 	[MDP_INTF8_7xxx_INTR] = {
159 		MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_CLEAR,
160 		MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_EN,
161 		MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_STATUS
162 	},
163 };
164 
165 #define DPU_IRQ_REG(irq_idx)	(irq_idx / 32)
166 #define DPU_IRQ_MASK(irq_idx)	(BIT(irq_idx % 32))
167 
168 /**
169  * dpu_core_irq_callback_handler - dispatch core interrupts
170  * @dpu_kms:		Pointer to DPU's KMS structure
171  * @irq_idx:		interrupt index
172  */
173 static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx)
174 {
175 	VERB("irq_idx=%d\n", irq_idx);
176 
177 	if (!dpu_kms->hw_intr->irq_tbl[irq_idx].cb)
178 		DRM_ERROR("no registered cb, idx:%d\n", irq_idx);
179 
180 	atomic_inc(&dpu_kms->hw_intr->irq_tbl[irq_idx].count);
181 
182 	/*
183 	 * Perform registered function callback
184 	 */
185 	dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx);
186 }
187 
188 irqreturn_t dpu_core_irq(struct msm_kms *kms)
189 {
190 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
191 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
192 	int reg_idx;
193 	int irq_idx;
194 	u32 irq_status;
195 	u32 enable_mask;
196 	int bit;
197 	unsigned long irq_flags;
198 
199 	if (!intr)
200 		return IRQ_NONE;
201 
202 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
203 	for (reg_idx = 0; reg_idx < ARRAY_SIZE(dpu_intr_set); reg_idx++) {
204 		if (!test_bit(reg_idx, &intr->irq_mask))
205 			continue;
206 
207 		/* Read interrupt status */
208 		irq_status = DPU_REG_READ(&intr->hw, dpu_intr_set[reg_idx].status_off);
209 
210 		/* Read enable mask */
211 		enable_mask = DPU_REG_READ(&intr->hw, dpu_intr_set[reg_idx].en_off);
212 
213 		/* and clear the interrupt */
214 		if (irq_status)
215 			DPU_REG_WRITE(&intr->hw, dpu_intr_set[reg_idx].clr_off,
216 				     irq_status);
217 
218 		/* Finally update IRQ status based on enable mask */
219 		irq_status &= enable_mask;
220 
221 		if (!irq_status)
222 			continue;
223 
224 		/*
225 		 * Search through matching intr status.
226 		 */
227 		while ((bit = ffs(irq_status)) != 0) {
228 			irq_idx = DPU_IRQ_IDX(reg_idx, bit - 1);
229 
230 			dpu_core_irq_callback_handler(dpu_kms, irq_idx);
231 
232 			/*
233 			 * When callback finish, clear the irq_status
234 			 * with the matching mask. Once irq_status
235 			 * is all cleared, the search can be stopped.
236 			 */
237 			irq_status &= ~BIT(bit - 1);
238 		}
239 	}
240 
241 	/* ensure register writes go through */
242 	wmb();
243 
244 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
245 
246 	return IRQ_HANDLED;
247 }
248 
249 static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx)
250 {
251 	int reg_idx;
252 	const struct dpu_intr_reg *reg;
253 	const char *dbgstr = NULL;
254 	uint32_t cache_irq_mask;
255 
256 	if (!intr)
257 		return -EINVAL;
258 
259 	if (irq_idx < 0 || irq_idx >= intr->total_irqs) {
260 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
261 		return -EINVAL;
262 	}
263 
264 	/*
265 	 * The cache_irq_mask and hardware RMW operations needs to be done
266 	 * under irq_lock and it's the caller's responsibility to ensure that's
267 	 * held.
268 	 */
269 	assert_spin_locked(&intr->irq_lock);
270 
271 	reg_idx = DPU_IRQ_REG(irq_idx);
272 	reg = &dpu_intr_set[reg_idx];
273 
274 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
275 	if (cache_irq_mask & DPU_IRQ_MASK(irq_idx)) {
276 		dbgstr = "already ";
277 	} else {
278 		dbgstr = "";
279 
280 		cache_irq_mask |= DPU_IRQ_MASK(irq_idx);
281 		/* Cleaning any pending interrupt */
282 		DPU_REG_WRITE(&intr->hw, reg->clr_off, DPU_IRQ_MASK(irq_idx));
283 		/* Enabling interrupts with the new mask */
284 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
285 
286 		/* ensure register write goes through */
287 		wmb();
288 
289 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
290 	}
291 
292 	pr_debug("DPU IRQ %d %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr,
293 			DPU_IRQ_MASK(irq_idx), cache_irq_mask);
294 
295 	return 0;
296 }
297 
298 static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, 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 (irq_idx < 0 || irq_idx >= intr->total_irqs) {
309 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
310 		return -EINVAL;
311 	}
312 
313 	/*
314 	 * The cache_irq_mask and hardware RMW operations needs to be done
315 	 * under irq_lock and it's the caller's responsibility to ensure that's
316 	 * held.
317 	 */
318 	assert_spin_locked(&intr->irq_lock);
319 
320 	reg_idx = DPU_IRQ_REG(irq_idx);
321 	reg = &dpu_intr_set[reg_idx];
322 
323 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
324 	if ((cache_irq_mask & DPU_IRQ_MASK(irq_idx)) == 0) {
325 		dbgstr = "already ";
326 	} else {
327 		dbgstr = "";
328 
329 		cache_irq_mask &= ~DPU_IRQ_MASK(irq_idx);
330 		/* Disable interrupts based on the new mask */
331 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
332 		/* Cleaning any pending interrupt */
333 		DPU_REG_WRITE(&intr->hw, reg->clr_off, DPU_IRQ_MASK(irq_idx));
334 
335 		/* ensure register write goes through */
336 		wmb();
337 
338 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
339 	}
340 
341 	pr_debug("DPU IRQ %d %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr,
342 			DPU_IRQ_MASK(irq_idx), cache_irq_mask);
343 
344 	return 0;
345 }
346 
347 static void dpu_clear_irqs(struct dpu_kms *dpu_kms)
348 {
349 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
350 	int i;
351 
352 	if (!intr)
353 		return;
354 
355 	for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
356 		if (test_bit(i, &intr->irq_mask))
357 			DPU_REG_WRITE(&intr->hw,
358 					dpu_intr_set[i].clr_off, 0xffffffff);
359 	}
360 
361 	/* ensure register writes go through */
362 	wmb();
363 }
364 
365 static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms)
366 {
367 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
368 	int i;
369 
370 	if (!intr)
371 		return;
372 
373 	for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
374 		if (test_bit(i, &intr->irq_mask))
375 			DPU_REG_WRITE(&intr->hw,
376 					dpu_intr_set[i].en_off, 0x00000000);
377 	}
378 
379 	/* ensure register writes go through */
380 	wmb();
381 }
382 
383 u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx)
384 {
385 	struct dpu_hw_intr *intr = dpu_kms->hw_intr;
386 	int reg_idx;
387 	unsigned long irq_flags;
388 	u32 intr_status;
389 
390 	if (!intr)
391 		return 0;
392 
393 	if (irq_idx < 0) {
394 		DPU_ERROR("[%pS] invalid irq_idx=%d\n",
395 				__builtin_return_address(0), irq_idx);
396 		return 0;
397 	}
398 
399 	if (irq_idx < 0 || irq_idx >= intr->total_irqs) {
400 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
401 		return 0;
402 	}
403 
404 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
405 
406 	reg_idx = DPU_IRQ_REG(irq_idx);
407 	intr_status = DPU_REG_READ(&intr->hw,
408 			dpu_intr_set[reg_idx].status_off) &
409 		DPU_IRQ_MASK(irq_idx);
410 	if (intr_status)
411 		DPU_REG_WRITE(&intr->hw, dpu_intr_set[reg_idx].clr_off,
412 				intr_status);
413 
414 	/* ensure register writes go through */
415 	wmb();
416 
417 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
418 
419 	return intr_status;
420 }
421 
422 static void __intr_offset(const struct dpu_mdss_cfg *m,
423 		void __iomem *addr, struct dpu_hw_blk_reg_map *hw)
424 {
425 	hw->blk_addr = addr + m->mdp[0].base;
426 }
427 
428 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
429 		const struct dpu_mdss_cfg *m)
430 {
431 	struct dpu_hw_intr *intr;
432 	int nirq = MDP_INTR_MAX * 32;
433 
434 	if (!addr || !m)
435 		return ERR_PTR(-EINVAL);
436 
437 	intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
438 	if (!intr)
439 		return ERR_PTR(-ENOMEM);
440 
441 	__intr_offset(m, addr, &intr->hw);
442 
443 	intr->total_irqs = nirq;
444 
445 	intr->irq_mask = m->mdss_irqs;
446 
447 	spin_lock_init(&intr->irq_lock);
448 
449 	return intr;
450 }
451 
452 void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
453 {
454 	kfree(intr);
455 }
456 
457 int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
458 		void (*irq_cb)(void *arg, int irq_idx),
459 		void *irq_arg)
460 {
461 	unsigned long irq_flags;
462 	int ret;
463 
464 	if (!irq_cb) {
465 		DPU_ERROR("invalid ird_idx:%d irq_cb:%ps\n", irq_idx, irq_cb);
466 		return -EINVAL;
467 	}
468 
469 	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
470 		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
471 		return -EINVAL;
472 	}
473 
474 	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
475 
476 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
477 
478 	if (unlikely(WARN_ON(dpu_kms->hw_intr->irq_tbl[irq_idx].cb))) {
479 		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
480 
481 		return -EBUSY;
482 	}
483 
484 	trace_dpu_core_irq_register_callback(irq_idx, irq_cb);
485 	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = irq_arg;
486 	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = irq_cb;
487 
488 	ret = dpu_hw_intr_enable_irq_locked(
489 				dpu_kms->hw_intr,
490 				irq_idx);
491 	if (ret)
492 		DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
493 					irq_idx);
494 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
495 
496 	trace_dpu_irq_register_success(irq_idx);
497 
498 	return 0;
499 }
500 
501 int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx)
502 {
503 	unsigned long irq_flags;
504 	int ret;
505 
506 	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
507 		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
508 		return -EINVAL;
509 	}
510 
511 	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
512 
513 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
514 	trace_dpu_core_irq_unregister_callback(irq_idx);
515 
516 	ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx);
517 	if (ret)
518 		DPU_ERROR("Fail to disable IRQ for irq_idx:%d: %d\n",
519 					irq_idx, ret);
520 
521 	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = NULL;
522 	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = NULL;
523 
524 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
525 
526 	trace_dpu_irq_unregister_success(irq_idx);
527 
528 	return 0;
529 }
530 
531 #ifdef CONFIG_DEBUG_FS
532 static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
533 {
534 	struct dpu_kms *dpu_kms = s->private;
535 	unsigned long irq_flags;
536 	int i, irq_count;
537 	void *cb;
538 
539 	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) {
540 		spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
541 		irq_count = atomic_read(&dpu_kms->hw_intr->irq_tbl[i].count);
542 		cb = dpu_kms->hw_intr->irq_tbl[i].cb;
543 		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
544 
545 		if (irq_count || cb)
546 			seq_printf(s, "idx:%d irq:%d cb:%ps\n", i, irq_count, cb);
547 	}
548 
549 	return 0;
550 }
551 
552 DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq);
553 
554 void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
555 		struct dentry *parent)
556 {
557 	debugfs_create_file("core_irq", 0600, parent, dpu_kms,
558 		&dpu_debugfs_core_irq_fops);
559 }
560 #endif
561 
562 void dpu_core_irq_preinstall(struct msm_kms *kms)
563 {
564 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
565 	int i;
566 
567 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
568 	dpu_clear_irqs(dpu_kms);
569 	dpu_disable_all_irqs(dpu_kms);
570 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
571 
572 	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
573 		atomic_set(&dpu_kms->hw_intr->irq_tbl[i].count, 0);
574 }
575 
576 void dpu_core_irq_uninstall(struct msm_kms *kms)
577 {
578 	struct dpu_kms *dpu_kms = to_dpu_kms(kms);
579 	int i;
580 
581 	if (!dpu_kms->hw_intr)
582 		return;
583 
584 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
585 	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
586 		if (dpu_kms->hw_intr->irq_tbl[i].cb)
587 			DPU_ERROR("irq_idx=%d still enabled/registered\n", i);
588 
589 	dpu_clear_irqs(dpu_kms);
590 	dpu_disable_all_irqs(dpu_kms);
591 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
592 }
593