18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2018 Loongson Technology Co., Ltd.
38c2ecf20Sopenharmony_ci * Authors:
48c2ecf20Sopenharmony_ci *	Chen Zhu <zhuchen@loongson.cn>
58c2ecf20Sopenharmony_ci *	Yaling Fang <fangyaling@loongson.cn>
68c2ecf20Sopenharmony_ci *	Dandan Zhang <zhangdandan@loongson.cn>
78c2ecf20Sopenharmony_ci *	Huacai Chen <chenhc@lemote.com>
88c2ecf20Sopenharmony_ci * This program is free software; you can redistribute  it and/or modify it
98c2ecf20Sopenharmony_ci * under  the terms of  the GNU General  Public License as published by the
108c2ecf20Sopenharmony_ci * Free Software Foundation;  either version 2 of the  License, or (at your
118c2ecf20Sopenharmony_ci * option) any later version.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "loongson_drv.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciirqreturn_t loongson_irq_handler(int irq, void *arg)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	unsigned int val;
198c2ecf20Sopenharmony_ci	struct drm_device *dev = (struct drm_device *) arg;
208c2ecf20Sopenharmony_ci	struct loongson_drm_device *ldev = dev->dev_private;
218c2ecf20Sopenharmony_ci	volatile void __iomem *base = ldev->mmio;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	val = readl(base + FB_INT_REG);
248c2ecf20Sopenharmony_ci	spin_lock(&loongson_reglock);
258c2ecf20Sopenharmony_ci	writel(val, base + FB_INT_REG);
268c2ecf20Sopenharmony_ci	spin_unlock(&loongson_reglock);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	if (val & BIT(INT_DVO0_FB_END)){
298c2ecf20Sopenharmony_ci		drm_crtc_handle_vblank(&ldev->lcrtc[0].base);
308c2ecf20Sopenharmony_ci	}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (val & BIT(INT_DVO1_FB_END)){
338c2ecf20Sopenharmony_ci		drm_crtc_handle_vblank(&ldev->lcrtc[1].base);
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	spin_lock(&loongson_reglock);
378c2ecf20Sopenharmony_ci	writel(ldev->int_reg, base + FB_INT_REG);
388c2ecf20Sopenharmony_ci	spin_unlock(&loongson_reglock);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_civoid loongson_irq_preinstall(struct drm_device *dev)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	unsigned long flags;
468c2ecf20Sopenharmony_ci	struct loongson_drm_device *ldev = dev->dev_private;
478c2ecf20Sopenharmony_ci	volatile void __iomem *base = ldev->mmio;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	/* disable interupt */
508c2ecf20Sopenharmony_ci	spin_lock_irqsave(&loongson_reglock, flags);
518c2ecf20Sopenharmony_ci	writel(0x0000 << 16, base + FB_INT_REG);
528c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&loongson_reglock, flags);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciint loongson_irq_postinstall(struct drm_device *dev)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	return 0;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_civoid loongson_irq_uninstall(struct drm_device *dev)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	unsigned long flags;
638c2ecf20Sopenharmony_ci	struct loongson_drm_device *ldev = dev->dev_private;
648c2ecf20Sopenharmony_ci	volatile void __iomem *base = ldev->mmio;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* disable interupt */
678c2ecf20Sopenharmony_ci	spin_lock_irqsave(&loongson_reglock, flags);
688c2ecf20Sopenharmony_ci	writel(0x0000 << 16, base + FB_INT_REG);
698c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&loongson_reglock, flags);
708c2ecf20Sopenharmony_ci}
71