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/interrupt.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/irq_cpu.h>
962306a36Sopenharmony_ci#include <asm/i8259.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <loongson.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic void i8259_irqdispatch(void)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	int irq;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci	irq = i8259_irq();
1862306a36Sopenharmony_ci	if (irq >= 0)
1962306a36Sopenharmony_ci		do_IRQ(irq);
2062306a36Sopenharmony_ci	else
2162306a36Sopenharmony_ci		spurious_interrupt();
2262306a36Sopenharmony_ci}
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciasmlinkage void mach_irq_dispatch(unsigned int pending)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	if (pending & CAUSEF_IP7)
2762306a36Sopenharmony_ci		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
2862306a36Sopenharmony_ci	else if (pending & CAUSEF_IP6) /* perf counter loverflow */
2962306a36Sopenharmony_ci		return;
3062306a36Sopenharmony_ci	else if (pending & CAUSEF_IP5)
3162306a36Sopenharmony_ci		i8259_irqdispatch();
3262306a36Sopenharmony_ci	else if (pending & CAUSEF_IP2)
3362306a36Sopenharmony_ci		bonito_irqdispatch();
3462306a36Sopenharmony_ci	else
3562306a36Sopenharmony_ci		spurious_interrupt();
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_civoid __init mach_init_irq(void)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	int irq;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* init all controller
4362306a36Sopenharmony_ci	 *   0-15	  ------> i8259 interrupt
4462306a36Sopenharmony_ci	 *   16-23	  ------> mips cpu interrupt
4562306a36Sopenharmony_ci	 *   32-63	  ------> bonito irq
4662306a36Sopenharmony_ci	 */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* most bonito irq should be level triggered */
4962306a36Sopenharmony_ci	LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR |
5062306a36Sopenharmony_ci	    LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* Sets the first-level interrupt dispatcher. */
5362306a36Sopenharmony_ci	mips_cpu_irq_init();
5462306a36Sopenharmony_ci	init_i8259_irqs();
5562306a36Sopenharmony_ci	bonito_irq_init();
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* bonito irq at IP2 */
5862306a36Sopenharmony_ci	irq = MIPS_CPU_IRQ_BASE + 2;
5962306a36Sopenharmony_ci	if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade", NULL))
6062306a36Sopenharmony_ci		pr_err("Failed to request irq %d (cascade)\n", irq);
6162306a36Sopenharmony_ci	/* 8259 irq at IP5 */
6262306a36Sopenharmony_ci	irq = MIPS_CPU_IRQ_BASE + 5;
6362306a36Sopenharmony_ci	if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade", NULL))
6462306a36Sopenharmony_ci		pr_err("Failed to request irq %d (cascade)\n", irq);
6562306a36Sopenharmony_ci}
66