Skip to content

Commit

Permalink
[PATCH] FRV: Use the generic IRQ stuff
Browse files Browse the repository at this point in the history
Make the FRV arch use the generic IRQ code rather than having its own
routines for doing so.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
David Howells authored and Linus Torvalds committed Sep 26, 2006
1 parent 8d6b5ee commit 1bcbba3
Show file tree
Hide file tree
Showing 18 changed files with 450 additions and 1,221 deletions.
8 changes: 7 additions & 1 deletion arch/frv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ config GENERIC_CALIBRATE_DELAY

config GENERIC_HARDIRQS
bool
default n
default y

config GENERIC_TIME
bool
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions arch/frv/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
157 changes: 101 additions & 56 deletions arch/frv/kernel/irq-mb93091.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand All @@ -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, \
}
static void frv_fpga_enable(unsigned int irq)
{
uint16_t imr = __get_IMR();

__FPGA(0, 0x0028),
__FPGA(1, 0x0050),
__FPGA(2, 0x1c00),
__FPGA(3, 0x6386),
};

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]);
}
115 changes: 74 additions & 41 deletions arch/frv/kernel/irq-mb93093.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* 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
Expand All @@ -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)))

Expand All @@ -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)
{
__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 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[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]);
}
Loading

0 comments on commit 1bcbba3

Please sign in to comment.