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

Commit 1bcbba30 authored by David Howells's avatar David Howells Committed by Linus Torvalds
Browse files

[PATCH] FRV: Use the generic IRQ stuff



Make the FRV arch use the generic IRQ code rather than having its own
routines for doing so.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8d6b5eee
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ config GENERIC_CALIBRATE_DELAY

config GENERIC_HARDIRQS
	bool
	default n
	default y

config GENERIC_TIME
	bool
@@ -251,6 +251,12 @@ config MB93091_NO_MB
endchoice
endif

config FUJITSU_MB93493
	bool "MB93493 Multimedia chip"
	help
	  Select this option if the MB93493 multimedia chip is going to be
	  used.

choice
	prompt "GP-Relative data support"
	default GPREL_DATA_8
+2 −3
Original line number Diff line number Diff line
@@ -10,15 +10,14 @@ extra-y:= head.o init_task.o vmlinux.lds
obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
	 process.o traps.o ptrace.o signal.o dma.o \
	 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
	 debug-stub.o irq.o irq-routing.o sleep.o uaccess.o
	 debug-stub.o irq.o sleep.o uaccess.o

obj-$(CONFIG_GDBSTUB)		+= gdb-stub.o gdb-io.o

obj-$(CONFIG_MB93091_VDK)	+= irq-mb93091.o
obj-$(CONFIG_MB93093_PDK)	+= irq-mb93093.o
obj-$(CONFIG_FUJITSU_MB93493)	+= irq-mb93493.o
obj-$(CONFIG_PM)		+= pm.o cmode.o
obj-$(CONFIG_MB93093_PDK)	+= pm-mb93093.o
obj-$(CONFIG_FUJITSU_MB93493)	+= irq-mb93493.o
obj-$(CONFIG_SYSCTL)		+= sysctl.o
obj-$(CONFIG_FUTEX)		+= futex.o
obj-$(CONFIG_MODULES)		+= module.o
+101 −56
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
#include <asm/irq-routing.h>

#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))

@@ -33,83 +32,129 @@
#define __get_IFR()	({ __reg16(0xffc0000c); })
#define __clr_IFR(M)	do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)

static void frv_fpga_doirq(struct irq_source *source);
static void frv_fpga_control(struct irq_group *group, int irq, int on);

/*****************************************************************************/
/*
 * FPGA IRQ multiplexor
 * on-motherboard FPGA PIC operations
 */
static struct irq_source frv_fpga[4] = {
#define __FPGA(X, M)					\
	[X] = {						\
		.muxname	= "fpga."#X,		\
		.irqmask	= M,			\
		.doirq		= frv_fpga_doirq,	\
	}

	__FPGA(0, 0x0028),
	__FPGA(1, 0x0050),
	__FPGA(2, 0x1c00),
	__FPGA(3, 0x6386),
};
static void frv_fpga_enable(unsigned int irq)
{
	uint16_t imr = __get_IMR();

static struct irq_group frv_fpga_irqs = {
	.first_irq	= IRQ_BASE_FPGA,
	.control	= frv_fpga_control,
	.sources = {
		[ 1] = &frv_fpga[3],
		[ 2] = &frv_fpga[3],
		[ 3] = &frv_fpga[0],
		[ 4] = &frv_fpga[1],
		[ 5] = &frv_fpga[0],
		[ 6] = &frv_fpga[1],
		[ 7] = &frv_fpga[3],
		[ 8] = &frv_fpga[3],
		[ 9] = &frv_fpga[3],
		[10] = &frv_fpga[2],
		[11] = &frv_fpga[2],
		[12] = &frv_fpga[2],
		[13] = &frv_fpga[3],
		[14] = &frv_fpga[3],
	},
};
	imr &= ~(1 << (irq - IRQ_BASE_FPGA));

	__set_IMR(imr);
}

static void frv_fpga_control(struct irq_group *group, int index, int on)
static void frv_fpga_disable(unsigned int irq)
{
	uint16_t imr = __get_IMR();

	if (on)
		imr &= ~(1 << index);
	else
		imr |= 1 << index;
	imr |= 1 << (irq - IRQ_BASE_FPGA);

	__set_IMR(imr);
}

static void frv_fpga_doirq(struct irq_source *source)
static void frv_fpga_ack(unsigned int irq)
{
	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
}

static void frv_fpga_end(unsigned int irq)
{
}

static struct irq_chip frv_fpga_pic = {
	.name		= "mb93091",
	.enable		= frv_fpga_enable,
	.disable	= frv_fpga_disable,
	.ack		= frv_fpga_ack,
	.mask		= frv_fpga_disable,
	.unmask		= frv_fpga_enable,
	.end		= frv_fpga_end,
};

/*
 * FPGA PIC interrupt handler
 */
static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
{
	uint16_t mask, imr;
	uint16_t imr, mask = (unsigned long) _mask;
	irqreturn_t iret = 0;

	imr = __get_IMR();
	mask = source->irqmask & ~imr & __get_IFR();
	if (mask) {
		__set_IMR(imr | mask);
		__clr_IFR(mask);
		distribute_irqs(&frv_fpga_irqs, mask);
		__set_IMR(imr);
	mask = mask & ~imr & __get_IFR();

	/* poll all the triggered IRQs */
	while (mask) {
		int irq;

		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
		irq = 31 - irq;
		mask &= ~(1 << irq);

		if (__do_IRQ(IRQ_BASE_FPGA + irq, regs))
			iret |= IRQ_HANDLED;
	}

	return iret;
}

/*
 * define an interrupt action for each FPGA PIC output
 * - use dev_id to indicate the FPGA PIC input to output mappings
 */
static struct irqaction fpga_irq[4]  = {
	[0] = {
		.handler	= fpga_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "fpga.0",
		.dev_id		= (void *) 0x0028UL,
	},
	[1] = {
		.handler	= fpga_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "fpga.1",
		.dev_id		= (void *) 0x0050UL,
	},
	[2] = {
		.handler	= fpga_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "fpga.2",
		.dev_id		= (void *) 0x1c00UL,
	},
	[3] = {
		.handler	= fpga_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "fpga.3",
		.dev_id		= (void *) 0x6386UL,
	}
};

/*
 * initialise the motherboard FPGA's PIC
 */
void __init fpga_init(void)
{
	int irq;

	/* all PIC inputs are all set to be low-level driven, apart from the
	 * NMI button (15) which is fixed at falling-edge
	 */
	__set_IMR(0x7ffe);
	__clr_IFR(0x0000);

	frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0);
	frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1);
	frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2);
	frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3);
	frv_irq_set_group(&frv_fpga_irqs);
	for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
		set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);

	set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);

	/* the FPGA drives the first four external IRQ inputs on the CPU PIC */
	setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
	setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
	setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
	setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
}
+74 −41
Original line number Diff line number Diff line
/* irq-mb93093.c: MB93093 FPGA interrupt handling
 *
 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
#include <asm/irq-routing.h>

#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))

@@ -33,66 +32,100 @@
#define __get_IFR()	({ __reg16(0x02); })
#define __clr_IFR(M)	do { __reg16(0x02) = ~(M); wmb(); } while(0)

static void frv_fpga_doirq(struct irq_source *source);
static void frv_fpga_control(struct irq_group *group, int irq, int on);

/*****************************************************************************/
/*
 * FPGA IRQ multiplexor
 * off-CPU FPGA PIC operations
 */
static struct irq_source frv_fpga[4] = {
#define __FPGA(X, M)					\
	[X] = {						\
		.muxname	= "fpga."#X,		\
		.irqmask	= M,			\
		.doirq		= frv_fpga_doirq,	\
	}

	__FPGA(0, 0x0700),
};
static void frv_fpga_enable(unsigned int irq)
{
	uint16_t imr = __get_IMR();

static struct irq_group frv_fpga_irqs = {
	.first_irq	= IRQ_BASE_FPGA,
	.control	= frv_fpga_control,
	.sources = {
		[ 8] = &frv_fpga[0],
		[ 9] = &frv_fpga[0],
		[10] = &frv_fpga[0],
	},
};
	imr &= ~(1 << (irq - IRQ_BASE_FPGA));

	__set_IMR(imr);
}

static void frv_fpga_control(struct irq_group *group, int index, int on)
static void frv_fpga_disable(unsigned int irq)
{
	uint16_t imr = __get_IMR();

	if (on)
		imr &= ~(1 << index);
	else
		imr |= 1 << index;
	imr |= 1 << (irq - IRQ_BASE_FPGA);

	__set_IMR(imr);
}

static void frv_fpga_doirq(struct irq_source *source)
static void frv_fpga_ack(unsigned int irq)
{
	uint16_t mask, imr;
	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
}

static void frv_fpga_end(unsigned int irq)
{
}

static struct irq_chip frv_fpga_pic = {
	.name		= "mb93093",
	.enable		= frv_fpga_enable,
	.disable	= frv_fpga_disable,
	.ack		= frv_fpga_ack,
	.mask		= frv_fpga_disable,
	.unmask		= frv_fpga_enable,
	.end		= frv_fpga_end,
};

/*
 * FPGA PIC interrupt handler
 */
static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
{
	uint16_t imr, mask = (unsigned long) _mask;
	irqreturn_t iret = 0;

	imr = __get_IMR();
	mask = source->irqmask & ~imr & __get_IFR();
	if (mask) {
		__set_IMR(imr | mask);
		__clr_IFR(mask);
		distribute_irqs(&frv_fpga_irqs, mask);
		__set_IMR(imr);
	mask = mask & ~imr & __get_IFR();

	/* poll all the triggered IRQs */
	while (mask) {
		int irq;

		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
		irq = 31 - irq;
		mask &= ~(1 << irq);

		if (__do_IRQ(IRQ_BASE_FPGA + irq, regs))
			iret |= IRQ_HANDLED;
	}

	return iret;
}

/*
 * define an interrupt action for each FPGA PIC output
 * - use dev_id to indicate the FPGA PIC input to output mappings
 */
static struct irqaction fpga_irq[1]  = {
	[0] = {
		.handler	= fpga_interrupt,
		.flags		= IRQF_DISABLED,
		.mask		= CPU_MASK_NONE,
		.name		= "fpga.0",
		.dev_id		= (void *) 0x0700UL,
	}
};

/*
 * initialise the motherboard FPGA's PIC
 */
void __init fpga_init(void)
{
	int irq;

	/* all PIC inputs are all set to be edge triggered */
	__set_IMR(0x0700);
	__clr_IFR(0x0000);

	frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2);
	frv_irq_set_group(&frv_fpga_irqs);
	for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
		set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);

	/* the FPGA drives external IRQ input #2 on the CPU PIC */
	setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
}
+108 −59
Original line number Diff line number Diff line
/* irq-mb93493.c: MB93493 companion chip interrupt handler
 *
 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
@@ -24,84 +24,133 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
#include <asm/irq-routing.h>
#include <asm/mb93493-irqs.h>
#include <asm/mb93493-regs.h>

static void frv_mb93493_doirq(struct irq_source *source);
#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))

#define IRQ_ROUTING					\
	(IRQ_ROUTE_ONE(IRQ_MB93493_VDC)		|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_VCC)		|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_USB)		|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_GPIO)	|	\
	 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))

/*****************************************************************************/
/*
 * MB93493 companion chip IRQ multiplexor
 * daughter board PIC operations
 */
static struct irq_source frv_mb93493[2] = {
	[0] = {
		.muxname		= "mb93493.0",
		.muxdata		= __region_CS3 + 0x3d0,
		.doirq			= frv_mb93493_doirq,
		.irqmask		= 0x0000,
	},
	[1] = {
		.muxname		= "mb93493.1",
		.muxdata		= __region_CS3 + 0x3d4,
		.doirq			= frv_mb93493_doirq,
		.irqmask		= 0x0000,
	},
};

static void frv_mb93493_control(struct irq_group *group, int index, int on)
static void frv_mb93493_enable(unsigned int irq)
{
	struct irq_source *source;
	uint32_t iqsr;
	volatile void *piqsr;

	if ((frv_mb93493[0].irqmask & (1 << index)))
		source = &frv_mb93493[0];
	if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
		piqsr = __addr_MB93493_IQSR(1);
	else
		source = &frv_mb93493[1];
		piqsr = __addr_MB93493_IQSR(0);

	iqsr = readl(source->muxdata);
	if (on)
		iqsr |= 1 << (index + 16);
	iqsr = readl(piqsr);
	iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
	writel(iqsr, piqsr);
}

static void frv_mb93493_disable(unsigned int irq)
{
	uint32_t iqsr;
	volatile void *piqsr;

	if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
		piqsr = __addr_MB93493_IQSR(1);
	else
		iqsr &= ~(1 << (index + 16));
		piqsr = __addr_MB93493_IQSR(0);

	writel(iqsr, source->muxdata);
	iqsr = readl(piqsr);
	iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
	writel(iqsr, piqsr);
}

static void frv_mb93493_ack(unsigned int irq)
{
}

static struct irq_group frv_mb93493_irqs = {
	.first_irq	= IRQ_BASE_MB93493,
	.control	= frv_mb93493_control,
static void frv_mb93493_end(unsigned int irq)
{
}

static struct irq_chip frv_mb93493_pic = {
	.name		= "mb93093",
	.enable		= frv_mb93493_enable,
	.disable	= frv_mb93493_disable,
	.ack		= frv_mb93493_ack,
	.mask		= frv_mb93493_disable,
	.unmask		= frv_mb93493_enable,
	.end		= frv_mb93493_end,
};

static void frv_mb93493_doirq(struct irq_source *source)
/*
 * MB93493 PIC interrupt handler
 */
static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs)
{
	uint32_t mask = readl(source->muxdata);
	mask = mask & (mask >> 16) & 0xffff;
	volatile void *piqsr = _piqsr;
	irqreturn_t iret = 0;
	uint32_t iqsr;

	iqsr = readl(piqsr);
	iqsr = iqsr & (iqsr >> 16) & 0xffff;

	/* poll all the triggered IRQs */
	while (iqsr) {
		int irq;

		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
		irq = 31 - irq;
		iqsr &= ~(1 << irq);

	if (mask)
		distribute_irqs(&frv_mb93493_irqs, mask);
		if (__do_IRQ(IRQ_BASE_MB93493 + irq, regs))
			iret |= IRQ_HANDLED;
	}

static void __init mb93493_irq_route(int irq, int source)
{
	frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493);
	frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source];
	return iret;
}

/*
 * define an interrupt action for each MB93493 PIC output
 * - use dev_id to indicate the MB93493 PIC input to output mappings
 */
static struct irqaction mb93493_irq[2]  = {
	[0] = {
		.handler	= mb93493_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "mb93493.0",
		.dev_id		= (void *) __addr_MB93493_IQSR(0),
	},
	[1] = {
		.handler	= mb93493_interrupt,
		.flags		= IRQF_DISABLED | IRQF_SHARED,
		.mask		= CPU_MASK_NONE,
		.name		= "mb93493.1",
		.dev_id		= (void *) __addr_MB93493_IQSR(1),
	}
};

void __init route_mb93493_irqs(void)
/*
 * initialise the motherboard MB93493's PIC
 */
void __init mb93493_init(void)
{
	frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0);
	frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1);

	frv_irq_set_group(&frv_mb93493_irqs);

	mb93493_irq_route(IRQ_MB93493_VDC,		IRQ_MB93493_VDC_ROUTE);
	mb93493_irq_route(IRQ_MB93493_VCC,		IRQ_MB93493_VCC_ROUTE);
	mb93493_irq_route(IRQ_MB93493_AUDIO_IN,		IRQ_MB93493_AUDIO_IN_ROUTE);
	mb93493_irq_route(IRQ_MB93493_I2C_0,		IRQ_MB93493_I2C_0_ROUTE);
	mb93493_irq_route(IRQ_MB93493_I2C_1,		IRQ_MB93493_I2C_1_ROUTE);
	mb93493_irq_route(IRQ_MB93493_USB,		IRQ_MB93493_USB_ROUTE);
	mb93493_irq_route(IRQ_MB93493_LOCAL_BUS,	IRQ_MB93493_LOCAL_BUS_ROUTE);
	mb93493_irq_route(IRQ_MB93493_PCMCIA,		IRQ_MB93493_PCMCIA_ROUTE);
	mb93493_irq_route(IRQ_MB93493_GPIO,		IRQ_MB93493_GPIO_ROUTE);
	mb93493_irq_route(IRQ_MB93493_AUDIO_OUT,	IRQ_MB93493_AUDIO_OUT_ROUTE);
	int irq;

	for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
		set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);

	/* the MB93493 drives external IRQ inputs on the CPU PIC */
	setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
	setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
}
Loading