Commit c1fe8d05 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Ard Biesheuvel
Browse files

ARM: riscpc: use GENERIC_IRQ_MULTI_HANDLER



This is one of the last platforms using the old entry path.
While this code path is spread over a few files, it is fairly
straightforward to convert it into an equivalent C version,
leaving the existing algorithm and all the priority handling
the same.

Unlike most irqchip drivers, this means reading the status
register(s) in a loop and always handling the highest-priority
irq first.

The IOMD_IRQREQC and IOMD_IRQREQD registers are not actaully
used here, but I left the code in place for the time being,
to keep the conversion as direct as possible. It could be
removed in a cleanup on top.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
[ardb: drop obsolete IOMD_IRQREQC/IOMD_IRQREQD handling]
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Tested-by: default avatarMarc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
parent d60ff2e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -444,6 +444,7 @@ config ARCH_RPC
	select ARM_HAS_SG_CHAIN
	select CPU_SA110
	select FIQ
	select GENERIC_IRQ_MULTI_HANDLER
	select HAVE_PATA_PLATFORM
	select ISA_DMA_API
	select LEGACY_TIMER_TICK
+0 −84
Original line number Diff line number Diff line
/*
 * arch/arm/include/asm/hardware/entry-macro-iomd.S
 *
 * Low-level IRQ helper macros for IOC/IOMD based platforms
 *
 * This file is licensed under  the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

/* IOC / IOMD based hardware */
#include <asm/hardware/iomd.h>

		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
		ldrb	\irqstat, [\base, #IOMD_IRQREQB]	@ get high priority first
		ldr	\tmp, =irq_prio_h
		teq	\irqstat, #0
#ifdef IOMD_BASE
		ldrbeq	\irqstat, [\base, #IOMD_DMAREQ]	@ get dma
		addeq	\tmp, \tmp, #256		@ irq_prio_h table size
		teqeq	\irqstat, #0
		bne	2406f
#endif
		ldrbeq	\irqstat, [\base, #IOMD_IRQREQA]	@ get low priority
		addeq	\tmp, \tmp, #256		@ irq_prio_d table size
		teqeq	\irqstat, #0
2406:		ldrbne	\irqnr, [\tmp, \irqstat]	@ get IRQ number
		.endm

/*
 * Interrupt table (incorporates priority).  Please note that we
 * rely on the order of these tables (see above code).
 */
		.align	5
irq_prio_h:	.byte	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
#ifdef IOMD_BASE
irq_prio_d:	.byte	 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
#endif
irq_prio_l:	.byte	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
		.byte	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+3 −2
Original line number Diff line number Diff line
@@ -2,10 +2,11 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/hardware.h>
#include <mach/entry-macro.S>

	.text
	.equ	ioc_base_high, IOC_BASE & 0xff000000
	.equ	ioc_base_low, IOC_BASE & 0x00ff0000

	.text
	.global	rpc_default_fiq_end
ENTRY(rpc_default_fiq_start)
	mov	r12, #ioc_base_high
+0 −13
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#include <mach/hardware.h>
#include <asm/hardware/entry-macro-iomd.S>

	.equ	ioc_base_high, IOC_BASE & 0xff000000
	.equ	ioc_base_low, IOC_BASE & 0x00ff0000

	.macro  get_irqnr_preamble, base, tmp
	mov	\base, #ioc_base_high		@ point at IOC
	.if	ioc_base_low
	orr	\base, \base, #ioc_base_low
	.endif
	.endm
+95 −0
Original line number Diff line number Diff line
@@ -14,6 +14,99 @@
#define CLR	0x04
#define MASK	0x08

static const u8 irq_prio_h[256] = {
	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
};

static const u8 irq_prio_d[256] = {
	 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
};

static const u8 irq_prio_l[256] = {
	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
};

static int iomd_get_irq_nr(void)
{
	int irq;
	u8 reg;

	/* get highest priority first */
	reg = readb(IOC_BASE + IOMD_IRQREQB);
	irq = irq_prio_h[reg];
	if (irq)
		return irq;

	/* get DMA  */
	reg = readb(IOC_BASE + IOMD_DMAREQ);
	irq = irq_prio_d[reg];
	if (irq)
		return irq;

	/* get low priority */
	reg = readb(IOC_BASE + IOMD_IRQREQA);
	irq = irq_prio_l[reg];
	if (irq)
		return irq;
	return 0;
}

static void iomd_handle_irq(struct pt_regs *regs)
{
	int irq;

	do {
		irq = iomd_get_irq_nr();
		if (irq)
			generic_handle_irq(irq);
	} while (irq);
}

static void __iomem *iomd_get_base(struct irq_data *d)
{
	void *cd = irq_data_get_irq_chip_data(d);
@@ -82,6 +175,8 @@ void __init rpc_init_irq(void)
	set_fiq_handler(&rpc_default_fiq_start,
		&rpc_default_fiq_end - &rpc_default_fiq_start);

	set_handle_irq(iomd_handle_irq);

	for (irq = 0; irq < NR_IRQS; irq++) {
		clr = IRQ_NOREQUEST;
		set = 0;