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

ARM: iop32x: use GENERIC_IRQ_MULTI_HANDLER



iop32x uses the entry-macro.S file for both the IRQ entry and for
hooking into the arch_ret_to_user code path. This is done because the
cp6 registers have to be enabled before accessing any of the interrupt
controller registers but have to be disabled when running in user space.

There is also a lazy-enable logic in cp6.c, but during a hardirq, we
know it has to be enabled.

Both the cp6-enable code and the code to read the IRQ status can be
lifted into the normal generic_handle_arch_irq() path, but the
cp6-disable code has to remain in the user return code. As nothing
other than iop32x uses this hook, just open-code it there with an
ifdef for the platform that can eventually be removed when iop32x
has reached the end of its life.

The cp6-enable path in the IRQ entry has an extra cp_wait barrier that
the trap version does not have, but it is harmless to do it in both
cases to simplify the logic here at the cost of a few extra cycles
for the trap.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
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 9d67412f
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -227,9 +227,6 @@ config GENERIC_ISA_DMA
config FIQ
	bool

config NEED_RET_TO_USER
	bool

config ARCH_MTD_XIP
	bool

@@ -371,9 +368,9 @@ config ARCH_IOP32X
	bool "IOP32x-based"
	depends on MMU
	select CPU_XSCALE
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIO_IOP
	select GPIOLIB
	select NEED_RET_TO_USER
	select FORCE_PCI
	select PLAT_IOP
	help
+9 −7
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

	.equ	NR_syscalls, __NR_syscalls

#ifdef CONFIG_NEED_RET_TO_USER
#include <mach/entry-macro.S>
#else
	.macro  arch_ret_to_user, tmp1, tmp2
	.endm
	.macro  arch_ret_to_user, tmp
#ifdef CONFIG_ARCH_IOP32X
	mrc	p15, 0, \tmp, c15, c1, 0
	tst	\tmp, #(1 << 6)
	bicne	\tmp, \tmp, #(1 << 6)
	mcrne	p15, 0, \tmp, c15, c1, 0	@ Disable cp6 access
#endif
	.endm

#include "entry-header.S"

@@ -55,7 +57,7 @@ __ret_fast_syscall:


	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr
	arch_ret_to_user r1

	restore_user_regs fast = 1, offset = S_OFF
 UNWIND(.fnend		)
@@ -128,7 +130,7 @@ no_work_pending:
	asm_trace_hardirqs_on save = 0

	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr
	arch_ret_to_user r1
	ct_user_enter save = 0

	restore_user_regs fast = 0, offset = 0
+9 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
#include <asm/traps.h>
#include <asm/ptrace.h>

static int cp6_trap(struct pt_regs *regs, unsigned int instr)
void iop_enable_cp6(void)
{
	u32 temp;

@@ -16,7 +16,15 @@ static int cp6_trap(struct pt_regs *regs, unsigned int instr)
		"mrc	p15, 0, %0, c15, c1, 0\n\t"
		"orr	%0, %0, #(1 << 6)\n\t"
		"mcr	p15, 0, %0, c15, c1, 0\n\t"
		"mrc	p15, 0, %0, c15, c1, 0\n\t"
		"mov	%0, %0\n\t"
		"sub	pc, pc, #4  @ cp_wait\n\t"
		: "=r"(temp));
}

static int cp6_trap(struct pt_regs *regs, unsigned int instr)
{
	iop_enable_cp6();

	return 0;
}
+0 −31
Original line number Diff line number Diff line
/*
 * arch/arm/mach-iop32x/include/mach/entry-macro.S
 *
 * Low-level IRQ helper macros for IOP32x-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.
 */
	.macro get_irqnr_preamble, base, tmp
	mrc	p15, 0, \tmp, c15, c1, 0
	orr	\tmp, \tmp, #(1 << 6)
	mcr	p15, 0, \tmp, c15, c1, 0	@ Enable cp6 access
	mrc	p15, 0, \tmp, c15, c1, 0
	mov	\tmp, \tmp
	sub	pc, pc, #4			@ cp_wait
	.endm

	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
	mrc     p6, 0, \irqstat, c8, c0, 0	@ Read IINTSRC
	cmp     \irqstat, #0
	clzne   \irqnr, \irqstat
	rsbne   \irqnr, \irqnr, #32
	.endm

	.macro arch_ret_to_user, tmp1, tmp2
	mrc	p15, 0, \tmp1, c15, c1, 0
	ands	\tmp2, \tmp1, #(1 << 6)
	bicne	\tmp1, \tmp1, #(1 << 6)
	mcrne	p15, 0, \tmp1, c15, c1, 0	@ Disable cp6 access
	.endm
+1 −0
Original line number Diff line number Diff line
@@ -225,6 +225,7 @@ extern int iop3xx_get_init_atu(void);
#include <linux/reboot.h>

void iop3xx_map_io(void);
void iop_enable_cp6(void);
void iop_init_cp6_handler(void);
void iop_init_time(unsigned long tickrate);
void iop3xx_restart(enum reboot_mode, const char *);
Loading