Skip to content

Commit

Permalink
ARM: iop32x: use GENERIC_IRQ_MULTI_HANDLER
Browse files Browse the repository at this point in the history
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: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Tested-by: Marc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
  • Loading branch information
Arnd Bergmann authored and Ard Biesheuvel committed Dec 6, 2021
1 parent 9d67412 commit 6f5d248
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 43 deletions.
5 changes: 1 addition & 4 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,6 @@ config GENERIC_ISA_DMA
config FIQ
bool

config NEED_RET_TO_USER
bool

config ARCH_MTD_XIP
bool

Expand Down Expand Up @@ -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
Expand Down
16 changes: 9 additions & 7 deletions arch/arm/kernel/entry-common.S
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion arch/arm/mach-iop32x/cp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
Expand Down
31 changes: 0 additions & 31 deletions arch/arm/mach-iop32x/include/mach/entry-macro.S

This file was deleted.

1 change: 1 addition & 0 deletions arch/arm/mach-iop32x/iop3xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
23 changes: 23 additions & 0 deletions arch/arm/mach-iop32x/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ static void intstr_write(u32 val)
asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
}

static u32 iintsrc_read(void)
{
int irq;

asm volatile("mrc p6, 0, %0, c8, c0, 0" : "=r" (irq));

return irq;
}

static void
iop32x_irq_mask(struct irq_data *d)
{
Expand All @@ -50,11 +59,25 @@ struct irq_chip ext_chip = {
.irq_unmask = iop32x_irq_unmask,
};

void iop_handle_irq(struct pt_regs *regs)
{
u32 mask;

iop_enable_cp6();

do {
mask = iintsrc_read();
if (mask)
generic_handle_irq(fls(mask));
} while (mask);
}

void __init iop32x_init_irq(void)
{
int i;

iop_init_cp6_handler();
set_handle_irq(iop_handle_irq);

intctl_write(0);
intstr_write(0);
Expand Down

0 comments on commit 6f5d248

Please sign in to comment.