1 /*
2  * Copyright (c) 2018 Loongson Technology Co., Ltd.
3  * Authors:
4  *	Chen Zhu <zhuchen@loongson.cn>
5  *	Yaling Fang <fangyaling@loongson.cn>
6  *	Dandan Zhang <zhangdandan@loongson.cn>
7  *	Huacai Chen <chenhc@lemote.com>
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 
14 #include "loongson_drv.h"
15 
loongson_irq_handler(int irq, void *arg)16 irqreturn_t loongson_irq_handler(int irq, void *arg)
17 {
18 	unsigned int val;
19 	struct drm_device *dev = (struct drm_device *) arg;
20 	struct loongson_drm_device *ldev = dev->dev_private;
21 	volatile void __iomem *base = ldev->mmio;
22 
23 	val = readl(base + FB_INT_REG);
24 	spin_lock(&loongson_reglock);
25 	writel(val, base + FB_INT_REG);
26 	spin_unlock(&loongson_reglock);
27 
28 	if (val & BIT(INT_DVO0_FB_END)){
29 		drm_crtc_handle_vblank(&ldev->lcrtc[0].base);
30 	}
31 
32 	if (val & BIT(INT_DVO1_FB_END)){
33 		drm_crtc_handle_vblank(&ldev->lcrtc[1].base);
34 	}
35 
36 	spin_lock(&loongson_reglock);
37 	writel(ldev->int_reg, base + FB_INT_REG);
38 	spin_unlock(&loongson_reglock);
39 
40 	return IRQ_HANDLED;
41 }
42 
loongson_irq_preinstall(struct drm_device *dev)43 void loongson_irq_preinstall(struct drm_device *dev)
44 {
45 	unsigned long flags;
46 	struct loongson_drm_device *ldev = dev->dev_private;
47 	volatile void __iomem *base = ldev->mmio;
48 
49 	/* disable interupt */
50 	spin_lock_irqsave(&loongson_reglock, flags);
51 	writel(0x0000 << 16, base + FB_INT_REG);
52 	spin_unlock_irqrestore(&loongson_reglock, flags);
53 }
54 
loongson_irq_postinstall(struct drm_device *dev)55 int loongson_irq_postinstall(struct drm_device *dev)
56 {
57 	return 0;
58 }
59 
loongson_irq_uninstall(struct drm_device *dev)60 void loongson_irq_uninstall(struct drm_device *dev)
61 {
62 	unsigned long flags;
63 	struct loongson_drm_device *ldev = dev->dev_private;
64 	volatile void __iomem *base = ldev->mmio;
65 
66 	/* disable interupt */
67 	spin_lock_irqsave(&loongson_reglock, flags);
68 	writel(0x0000 << 16, base + FB_INT_REG);
69 	spin_unlock_irqrestore(&loongson_reglock, flags);
70 }
71