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