Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37c42a74 authored by Maxime Bizon's avatar Maxime Bizon Committed by Ralf Baechle
Browse files

MIPS: BCM63XX: Prepare irq code to handle different external irq hardware implementation.



External irq only works for 6348, change code to prepare support of
other CPUs.

Signed-off-by: default avatarMaxime Bizon <mbizon@freebox.fr>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2895/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent f61cced9
Loading
Loading
Loading
Loading
+67 −37
Original line number Diff line number Diff line
@@ -25,18 +25,32 @@ static void __dispatch_internal(void) __maybe_unused;
#ifdef CONFIG_BCM63XX_CPU_6338
#define irq_stat_reg		PERF_IRQSTAT_6338_REG
#define irq_mask_reg		PERF_IRQMASK_6338_REG
#define is_ext_irq_cascaded	0
#define ext_irq_start		0
#define ext_irq_end		0
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
#define irq_stat_reg		PERF_IRQSTAT_6345_REG
#define irq_mask_reg		PERF_IRQMASK_6345_REG
#define is_ext_irq_cascaded	0
#define ext_irq_start		0
#define ext_irq_end		0
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
#define irq_stat_reg		PERF_IRQSTAT_6348_REG
#define irq_mask_reg		PERF_IRQMASK_6348_REG
#define dispatch_internal	__dispatch_internal
#define is_ext_irq_cascaded	0
#define ext_irq_start		0
#define ext_irq_end		0
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
#define irq_stat_reg		PERF_IRQSTAT_6358_REG
#define irq_mask_reg		PERF_IRQMASK_6358_REG
#define dispatch_internal	__dispatch_internal
#define is_ext_irq_cascaded	1
#define ext_irq_start		(BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
#define ext_irq_end		(BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
#endif

#define dispatch_internal	__dispatch_internal
@@ -51,6 +65,8 @@ static inline void bcm63xx_init_irq(void)

static u32 irq_stat_addr, irq_mask_addr;
static void (*dispatch_internal)(void);
static int is_ext_irq_cascaded;
static unsigned int ext_irq_start, ext_irq_end;

static void bcm63xx_init_irq(void)
{
@@ -73,6 +89,9 @@ static void bcm63xx_init_irq(void)
	case BCM6358_CPU_ID:
		irq_stat_addr += PERF_IRQSTAT_6358_REG;
		irq_mask_addr += PERF_IRQMASK_6358_REG;
		is_ext_irq_cascaded = 1;
		ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
		ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
		break;
	default:
		BUG();
@@ -84,6 +103,10 @@ static void bcm63xx_init_irq(void)

static inline void handle_internal(int intbit)
{
	if (is_ext_irq_cascaded &&
	    intbit >= ext_irq_start && intbit <= ext_irq_end)
		do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
	else
		do_IRQ(intbit + IRQ_INTERNAL_BASE);
}

@@ -128,6 +151,7 @@ asmlinkage void plat_irq_dispatch(void)
			do_IRQ(7);
		if (cause & CAUSEF_IP2)
			dispatch_internal();
		if (!is_ext_irq_cascaded) {
			if (cause & CAUSEF_IP3)
				do_IRQ(IRQ_EXT_0);
			if (cause & CAUSEF_IP4)
@@ -136,6 +160,7 @@ asmlinkage void plat_irq_dispatch(void)
				do_IRQ(IRQ_EXT_2);
			if (cause & CAUSEF_IP6)
				do_IRQ(IRQ_EXT_3);
		}
	} while (1);
}

@@ -143,9 +168,8 @@ asmlinkage void plat_irq_dispatch(void)
 * internal IRQs operations: only mask/unmask on PERF irq mask
 * register.
 */
static inline void bcm63xx_internal_irq_mask(struct irq_data *d)
static void internal_irq_mask(unsigned int irq)
{
	unsigned int irq = d->irq - IRQ_INTERNAL_BASE;
	u32 mask;

	mask = bcm_readl(irq_mask_addr);
@@ -153,9 +177,8 @@ static inline void bcm63xx_internal_irq_mask(struct irq_data *d)
	bcm_writel(mask, irq_mask_addr);
}

static void bcm63xx_internal_irq_unmask(struct irq_data *d)
static void internal_irq_unmask(unsigned int irq)
{
	unsigned int irq = d->irq - IRQ_INTERNAL_BASE;
	u32 mask;

	mask = bcm_readl(irq_mask_addr);
@@ -163,33 +186,47 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d)
	bcm_writel(mask, irq_mask_addr);
}

static void bcm63xx_internal_irq_mask(struct irq_data *d)
{
	internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
}

static void bcm63xx_internal_irq_unmask(struct irq_data *d)
{
	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
}

/*
 * external IRQs operations: mask/unmask and clear on PERF external
 * irq control register.
 */
static void bcm63xx_external_irq_mask(struct irq_data *d)
{
	unsigned int irq = d->irq - IRQ_EXT_BASE;
	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
	u32 reg;

	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
	reg &= ~EXTIRQ_CFG_MASK(irq);
	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
	if (is_ext_irq_cascaded)
		internal_irq_mask(irq + ext_irq_start);
}

static void bcm63xx_external_irq_unmask(struct irq_data *d)
{
	unsigned int irq = d->irq - IRQ_EXT_BASE;
	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
	u32 reg;

	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
	reg |= EXTIRQ_CFG_MASK(irq);
	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
	if (is_ext_irq_cascaded)
		internal_irq_unmask(irq + ext_irq_start);
}

static void bcm63xx_external_irq_clear(struct irq_data *d)
{
	unsigned int irq = d->irq - IRQ_EXT_BASE;
	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
	u32 reg;

	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
@@ -197,25 +234,10 @@ static void bcm63xx_external_irq_clear(struct irq_data *d)
	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
}

static unsigned int bcm63xx_external_irq_startup(struct irq_data *d)
{
	set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE));
	irq_enable_hazard();
	bcm63xx_external_irq_unmask(d);
	return 0;
}

static void bcm63xx_external_irq_shutdown(struct irq_data *d)
{
	bcm63xx_external_irq_mask(d);
	clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE));
	irq_disable_hazard();
}

static int bcm63xx_external_irq_set_type(struct irq_data *d,
					 unsigned int flow_type)
{
	unsigned int irq = d->irq - IRQ_EXT_BASE;
	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
	u32 reg;

	flow_type &= IRQ_TYPE_SENSE_MASK;
@@ -275,9 +297,6 @@ static struct irq_chip bcm63xx_internal_irq_chip = {

static struct irq_chip bcm63xx_external_irq_chip = {
	.name		= "bcm63xx_epic",
	.irq_startup	= bcm63xx_external_irq_startup,
	.irq_shutdown	= bcm63xx_external_irq_shutdown,

	.irq_ack	= bcm63xx_external_irq_clear,

	.irq_mask	= bcm63xx_external_irq_mask,
@@ -292,6 +311,12 @@ static struct irqaction cpu_ip2_cascade_action = {
	.flags		= IRQF_NO_THREAD,
};

static struct irqaction cpu_ext_cascade_action = {
	.handler	= no_action,
	.name		= "cascade_extirq",
	.flags		= IRQF_NO_THREAD,
};

void __init arch_init_irq(void)
{
	int i;
@@ -302,9 +327,14 @@ void __init arch_init_irq(void)
		irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
					 handle_level_irq);

	for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i)
	for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + 4; ++i)
		irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
					 handle_edge_irq);

	setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action);
	if (!is_ext_irq_cascaded) {
		for (i = 3; i < 7; ++i)
			setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
	}

	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
}
+5 −7
Original line number Diff line number Diff line
@@ -3,13 +3,11 @@

#include <bcm63xx_cpu.h>

#define IRQ_MIPS_BASE			0
#define IRQ_INTERNAL_BASE		8

#define IRQ_EXT_BASE			(IRQ_MIPS_BASE + 3)
#define IRQ_EXT_0			(IRQ_EXT_BASE + 0)
#define IRQ_EXT_1			(IRQ_EXT_BASE + 1)
#define IRQ_EXT_2			(IRQ_EXT_BASE + 2)
#define IRQ_EXT_3			(IRQ_EXT_BASE + 3)
#define IRQ_EXTERNAL_BASE		100
#define IRQ_EXT_0			(IRQ_EXTERNAL_BASE + 0)
#define IRQ_EXT_1			(IRQ_EXTERNAL_BASE + 1)
#define IRQ_EXT_2			(IRQ_EXTERNAL_BASE + 2)
#define IRQ_EXT_3			(IRQ_EXTERNAL_BASE + 3)

#endif /* ! BCM63XX_IRQ_H_ */
+7 −0
Original line number Diff line number Diff line
#ifndef __ASM_MACH_BCM63XX_IRQ_H
#define __ASM_MACH_BCM63XX_IRQ_H

#define NR_IRQS	128
#define MIPS_CPU_IRQ_BASE 0

#endif