d1bef4ed5f
This patch-queue improves the generic IRQ layer to be truly generic, by adding various abstractions and features to it, without impacting existing functionality. While the queue can be best described as "fix and improve everything in the generic IRQ layer that we could think of", and thus it consists of many smaller features and lots of cleanups, the one feature that stands out most is the new 'irq chip' abstraction. The irq-chip abstraction is about describing and coding and IRQ controller driver by mapping its raw hardware capabilities [and quirks, if needed] in a straightforward way, without having to think about "IRQ flow" (level/edge/etc.) type of details. This stands in contrast with the current 'irq-type' model of genirq architectures, which 'mixes' raw hardware capabilities with 'flow' details. The patchset supports both types of irq controller designs at once, and converts i386 and x86_64 to the new irq-chip design. As a bonus side-effect of the irq-chip approach, chained interrupt controllers (master/slave PIC constructs, etc.) are now supported by design as well. The end result of this patchset intends to be simpler architecture-level code and more consolidation between architectures. We reused many bits of code and many concepts from Russell King's ARM IRQ layer, the merging of which was one of the motivations for this patchset. This patch: rename desc->handler to desc->chip. Originally i did not want to do this, because it's a big patch. But having both "desc->handler", "desc->handle_irq" and "action->handler" caused a large degree of confusion and made the code appear alot less clean than it truly is. I have also attempted a dual approach as well by introducing a desc->chip alias - but that just wasnt robust enough and broke frequently. So lets get over with this quickly. The conversion was done automatically via scripts and converts all the code in the kernel. This renaming patch is the first one amongst the patches, so that the remaining patches can stay flexible and can be merged and split up without having some big monolithic patch act as a merge barrier. [akpm@osdl.org: build fix] [akpm@osdl.org: another build fix] Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
244 lines
6.3 KiB
C
244 lines
6.3 KiB
C
/*
|
|
* linux/arch/mips/tx4938/toshiba_rbtx4938/irq.c
|
|
*
|
|
* Toshiba RBTX4938 specific interrupt handlers
|
|
* Copyright (C) 2000-2001 Toshiba Corporation
|
|
*
|
|
* 2003-2005 (c) MontaVista Software, Inc. 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.
|
|
*
|
|
* Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
|
|
*/
|
|
|
|
/*
|
|
IRQ Device
|
|
|
|
16 TX4938-CP0/00 Software 0
|
|
17 TX4938-CP0/01 Software 1
|
|
18 TX4938-CP0/02 Cascade TX4938-CP0
|
|
19 TX4938-CP0/03 Multiplexed -- do not use
|
|
20 TX4938-CP0/04 Multiplexed -- do not use
|
|
21 TX4938-CP0/05 Multiplexed -- do not use
|
|
22 TX4938-CP0/06 Multiplexed -- do not use
|
|
23 TX4938-CP0/07 CPU TIMER
|
|
|
|
24 TX4938-PIC/00
|
|
25 TX4938-PIC/01
|
|
26 TX4938-PIC/02 Cascade RBTX4938-IOC
|
|
27 TX4938-PIC/03 RBTX4938 RTL-8019AS Ethernet
|
|
28 TX4938-PIC/04
|
|
29 TX4938-PIC/05 TX4938 ETH1
|
|
30 TX4938-PIC/06 TX4938 ETH0
|
|
31 TX4938-PIC/07
|
|
32 TX4938-PIC/08 TX4938 SIO 0
|
|
33 TX4938-PIC/09 TX4938 SIO 1
|
|
34 TX4938-PIC/10 TX4938 DMA0
|
|
35 TX4938-PIC/11 TX4938 DMA1
|
|
36 TX4938-PIC/12 TX4938 DMA2
|
|
37 TX4938-PIC/13 TX4938 DMA3
|
|
38 TX4938-PIC/14
|
|
39 TX4938-PIC/15
|
|
40 TX4938-PIC/16 TX4938 PCIC
|
|
41 TX4938-PIC/17 TX4938 TMR0
|
|
42 TX4938-PIC/18 TX4938 TMR1
|
|
43 TX4938-PIC/19 TX4938 TMR2
|
|
44 TX4938-PIC/20
|
|
45 TX4938-PIC/21
|
|
46 TX4938-PIC/22 TX4938 PCIERR
|
|
47 TX4938-PIC/23
|
|
48 TX4938-PIC/24
|
|
49 TX4938-PIC/25
|
|
50 TX4938-PIC/26
|
|
51 TX4938-PIC/27
|
|
52 TX4938-PIC/28
|
|
53 TX4938-PIC/29
|
|
54 TX4938-PIC/30
|
|
55 TX4938-PIC/31 TX4938 SPI
|
|
|
|
56 RBTX4938-IOC/00 PCI-D
|
|
57 RBTX4938-IOC/01 PCI-C
|
|
58 RBTX4938-IOC/02 PCI-B
|
|
59 RBTX4938-IOC/03 PCI-A
|
|
60 RBTX4938-IOC/04 RTC
|
|
61 RBTX4938-IOC/05 ATA
|
|
62 RBTX4938-IOC/06 MODEM
|
|
63 RBTX4938-IOC/07 SWINT
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/swap.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/timex.h>
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/page.h>
|
|
#include <asm/io.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/processor.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/reboot.h>
|
|
#include <asm/time.h>
|
|
#include <linux/bootmem.h>
|
|
#include <asm/tx4938/rbtx4938.h>
|
|
|
|
static unsigned int toshiba_rbtx4938_irq_ioc_startup(unsigned int irq);
|
|
static void toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq);
|
|
static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
|
|
static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
|
|
static void toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq);
|
|
static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq);
|
|
|
|
DEFINE_SPINLOCK(toshiba_rbtx4938_ioc_lock);
|
|
|
|
#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
|
|
static struct hw_interrupt_type toshiba_rbtx4938_irq_ioc_type = {
|
|
.typename = TOSHIBA_RBTX4938_IOC_NAME,
|
|
.startup = toshiba_rbtx4938_irq_ioc_startup,
|
|
.shutdown = toshiba_rbtx4938_irq_ioc_shutdown,
|
|
.enable = toshiba_rbtx4938_irq_ioc_enable,
|
|
.disable = toshiba_rbtx4938_irq_ioc_disable,
|
|
.ack = toshiba_rbtx4938_irq_ioc_mask_and_ack,
|
|
.end = toshiba_rbtx4938_irq_ioc_end,
|
|
.set_affinity = NULL
|
|
};
|
|
|
|
#define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000
|
|
#define TOSHIBA_RBTX4938_IOC_INTR_STAT 0xb7f0200a
|
|
|
|
int
|
|
toshiba_rbtx4938_irq_nested(int sw_irq)
|
|
{
|
|
u8 level3;
|
|
|
|
level3 = reg_rd08(TOSHIBA_RBTX4938_IOC_INTR_STAT) & 0xff;
|
|
if (level3) {
|
|
/* must use fls so onboard ATA has priority */
|
|
sw_irq = TOSHIBA_RBTX4938_IRQ_IOC_BEG + fls(level3) - 1;
|
|
}
|
|
|
|
wbflush();
|
|
return sw_irq;
|
|
}
|
|
|
|
static struct irqaction toshiba_rbtx4938_irq_ioc_action = {
|
|
.handler = no_action,
|
|
.flags = 0,
|
|
.mask = CPU_MASK_NONE,
|
|
.name = TOSHIBA_RBTX4938_IOC_NAME,
|
|
};
|
|
|
|
/**********************************************************************************/
|
|
/* Functions for ioc */
|
|
/**********************************************************************************/
|
|
static void __init
|
|
toshiba_rbtx4938_irq_ioc_init(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG;
|
|
i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) {
|
|
irq_desc[i].status = IRQ_DISABLED;
|
|
irq_desc[i].action = 0;
|
|
irq_desc[i].depth = 3;
|
|
irq_desc[i].chip = &toshiba_rbtx4938_irq_ioc_type;
|
|
}
|
|
|
|
setup_irq(RBTX4938_IRQ_IOCINT,
|
|
&toshiba_rbtx4938_irq_ioc_action);
|
|
}
|
|
|
|
static unsigned int
|
|
toshiba_rbtx4938_irq_ioc_startup(unsigned int irq)
|
|
{
|
|
toshiba_rbtx4938_irq_ioc_enable(irq);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq)
|
|
{
|
|
toshiba_rbtx4938_irq_ioc_disable(irq);
|
|
}
|
|
|
|
static void
|
|
toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
|
|
{
|
|
unsigned long flags;
|
|
volatile unsigned char v;
|
|
|
|
spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
|
|
|
|
v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
|
|
v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
|
|
TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
|
|
mmiowb();
|
|
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
|
|
|
|
spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
|
|
}
|
|
|
|
static void
|
|
toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
|
|
{
|
|
unsigned long flags;
|
|
volatile unsigned char v;
|
|
|
|
spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
|
|
|
|
v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
|
|
v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
|
|
TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
|
|
mmiowb();
|
|
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
|
|
|
|
spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
|
|
}
|
|
|
|
static void
|
|
toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq)
|
|
{
|
|
toshiba_rbtx4938_irq_ioc_disable(irq);
|
|
}
|
|
|
|
static void
|
|
toshiba_rbtx4938_irq_ioc_end(unsigned int irq)
|
|
{
|
|
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
|
|
toshiba_rbtx4938_irq_ioc_enable(irq);
|
|
}
|
|
}
|
|
|
|
extern void __init txx9_spi_irqinit(int irc_irq);
|
|
|
|
void __init arch_init_irq(void)
|
|
{
|
|
extern void tx4938_irq_init(void);
|
|
|
|
/* Now, interrupt control disabled, */
|
|
/* all IRC interrupts are masked, */
|
|
/* all IRC interrupt mode are Low Active. */
|
|
|
|
/* mask all IOC interrupts */
|
|
*rbtx4938_imask_ptr = 0;
|
|
|
|
/* clear SoftInt interrupts */
|
|
*rbtx4938_softint_ptr = 0;
|
|
tx4938_irq_init();
|
|
toshiba_rbtx4938_irq_ioc_init();
|
|
/* Onboard 10M Ether: High Active */
|
|
TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
|
|
|
|
if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
|
|
txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
|
|
}
|
|
|
|
wbflush();
|
|
}
|