18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
48c2ecf20Sopenharmony_ci * Author: Fuxin Zhang, zhangfx@lemote.com
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci#include <linux/delay.h>
78c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <loongson.h>
108c2ecf20Sopenharmony_ci/*
118c2ecf20Sopenharmony_ci * the first level int-handler will jump here if it is a bonito irq
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_civoid bonito_irqdispatch(void)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	u32 int_status;
168c2ecf20Sopenharmony_ci	int i;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	/* workaround the IO dma problem: let cpu looping to allow DMA finish */
198c2ecf20Sopenharmony_ci	int_status = LOONGSON_INTISR;
208c2ecf20Sopenharmony_ci	while (int_status & (1 << 10)) {
218c2ecf20Sopenharmony_ci		udelay(1);
228c2ecf20Sopenharmony_ci		int_status = LOONGSON_INTISR;
238c2ecf20Sopenharmony_ci	}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	/* Get pending sources, masked by current enables */
268c2ecf20Sopenharmony_ci	int_status = LOONGSON_INTISR & LOONGSON_INTEN;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	if (int_status) {
298c2ecf20Sopenharmony_ci		i = __ffs(int_status);
308c2ecf20Sopenharmony_ci		do_IRQ(LOONGSON_IRQ_BASE + i);
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciasmlinkage void plat_irq_dispatch(void)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	unsigned int pending;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	pending = read_c0_cause() & read_c0_status() & ST0_IM;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	/* machine-specific plat_irq_dispatch */
418c2ecf20Sopenharmony_ci	mach_irq_dispatch(pending);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_civoid __init arch_init_irq(void)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	/*
478c2ecf20Sopenharmony_ci	 * Clear all of the interrupts while we change the able around a bit.
488c2ecf20Sopenharmony_ci	 * int-handler is not on bootstrap
498c2ecf20Sopenharmony_ci	 */
508c2ecf20Sopenharmony_ci	clear_c0_status(ST0_IM | ST0_BEV);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/* no steer */
538c2ecf20Sopenharmony_ci	LOONGSON_INTSTEER = 0;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/*
568c2ecf20Sopenharmony_ci	 * Mask out all interrupt by writing "1" to all bit position in
578c2ecf20Sopenharmony_ci	 * the interrupt reset reg.
588c2ecf20Sopenharmony_ci	 */
598c2ecf20Sopenharmony_ci	LOONGSON_INTENCLR = ~0;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/* machine specific irq init */
628c2ecf20Sopenharmony_ci	mach_init_irq();
638c2ecf20Sopenharmony_ci}
64