162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
462306a36Sopenharmony_ci * Author: Fuxin Zhang, zhangfx@lemote.com
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include <linux/delay.h>
762306a36Sopenharmony_ci#include <linux/interrupt.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <loongson.h>
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci * the first level int-handler will jump here if it is a bonito irq
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_civoid bonito_irqdispatch(void)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	u32 int_status;
1662306a36Sopenharmony_ci	int i;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	/* workaround the IO dma problem: let cpu looping to allow DMA finish */
1962306a36Sopenharmony_ci	int_status = LOONGSON_INTISR;
2062306a36Sopenharmony_ci	while (int_status & (1 << 10)) {
2162306a36Sopenharmony_ci		udelay(1);
2262306a36Sopenharmony_ci		int_status = LOONGSON_INTISR;
2362306a36Sopenharmony_ci	}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	/* Get pending sources, masked by current enables */
2662306a36Sopenharmony_ci	int_status = LOONGSON_INTISR & LOONGSON_INTEN;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	if (int_status) {
2962306a36Sopenharmony_ci		i = __ffs(int_status);
3062306a36Sopenharmony_ci		do_IRQ(LOONGSON_IRQ_BASE + i);
3162306a36Sopenharmony_ci	}
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ciasmlinkage void plat_irq_dispatch(void)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	unsigned int pending;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	pending = read_c0_cause() & read_c0_status() & ST0_IM;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	/* machine-specific plat_irq_dispatch */
4162306a36Sopenharmony_ci	mach_irq_dispatch(pending);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid __init arch_init_irq(void)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	/*
4762306a36Sopenharmony_ci	 * Clear all of the interrupts while we change the able around a bit.
4862306a36Sopenharmony_ci	 * int-handler is not on bootstrap
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	clear_c0_status(ST0_IM | ST0_BEV);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* no steer */
5362306a36Sopenharmony_ci	LOONGSON_INTSTEER = 0;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/*
5662306a36Sopenharmony_ci	 * Mask out all interrupt by writing "1" to all bit position in
5762306a36Sopenharmony_ci	 * the interrupt reset reg.
5862306a36Sopenharmony_ci	 */
5962306a36Sopenharmony_ci	LOONGSON_INTENCLR = ~0;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	/* machine specific irq init */
6262306a36Sopenharmony_ci	mach_init_irq();
6362306a36Sopenharmony_ci}
64