~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/mips/jz4740/irq.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
 
3
 *  JZ4740 platform IRQ support
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify it
 
6
 *  under  the terms of the GNU General  Public License as published by the
 
7
 *  Free Software Foundation;  either version 2 of the License, or (at your
 
8
 *  option) any later version.
 
9
 *
 
10
 *  You should have received a copy of the GNU General Public License along
 
11
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 
12
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 
13
 *
 
14
 */
 
15
 
 
16
#include <linux/errno.h>
 
17
#include <linux/init.h>
 
18
#include <linux/types.h>
 
19
#include <linux/interrupt.h>
 
20
#include <linux/ioport.h>
 
21
#include <linux/timex.h>
 
22
#include <linux/slab.h>
 
23
#include <linux/delay.h>
 
24
 
 
25
#include <linux/debugfs.h>
 
26
#include <linux/seq_file.h>
 
27
 
 
28
#include <asm/io.h>
 
29
#include <asm/mipsregs.h>
 
30
#include <asm/irq_cpu.h>
 
31
 
 
32
#include <asm/mach-jz4740/base.h>
 
33
 
 
34
static void __iomem *jz_intc_base;
 
35
static uint32_t jz_intc_wakeup;
 
36
static uint32_t jz_intc_saved;
 
37
 
 
38
#define JZ_REG_INTC_STATUS      0x00
 
39
#define JZ_REG_INTC_MASK        0x04
 
40
#define JZ_REG_INTC_SET_MASK    0x08
 
41
#define JZ_REG_INTC_CLEAR_MASK  0x0c
 
42
#define JZ_REG_INTC_PENDING     0x10
 
43
 
 
44
#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
 
45
 
 
46
static void intc_irq_unmask(unsigned int irq)
 
47
{
 
48
        writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
 
49
}
 
50
 
 
51
static void intc_irq_mask(unsigned int irq)
 
52
{
 
53
        writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
 
54
}
 
55
 
 
56
static int intc_irq_set_wake(unsigned int irq, unsigned int on)
 
57
{
 
58
        if (on)
 
59
                jz_intc_wakeup |= IRQ_BIT(irq);
 
60
        else
 
61
                jz_intc_wakeup &= ~IRQ_BIT(irq);
 
62
 
 
63
        return 0;
 
64
}
 
65
 
 
66
static struct irq_chip intc_irq_type = {
 
67
        .name =         "INTC",
 
68
        .mask =         intc_irq_mask,
 
69
        .mask_ack =     intc_irq_mask,
 
70
        .unmask =       intc_irq_unmask,
 
71
        .set_wake =     intc_irq_set_wake,
 
72
};
 
73
 
 
74
static irqreturn_t jz4740_cascade(int irq, void *data)
 
75
{
 
76
        uint32_t irq_reg;
 
77
 
 
78
        irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
 
79
 
 
80
        if (irq_reg)
 
81
                generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
 
82
 
 
83
        return IRQ_HANDLED;
 
84
}
 
85
 
 
86
static struct irqaction jz4740_cascade_action = {
 
87
        .handler = jz4740_cascade,
 
88
        .name = "JZ4740 cascade interrupt",
 
89
};
 
90
 
 
91
void __init arch_init_irq(void)
 
92
{
 
93
        int i;
 
94
        mips_cpu_irq_init();
 
95
 
 
96
        jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
97
 
 
98
        for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
 
99
                intc_irq_mask(i);
 
100
                set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
 
101
        }
 
102
 
 
103
        setup_irq(2, &jz4740_cascade_action);
 
104
}
 
105
 
 
106
asmlinkage void plat_irq_dispatch(void)
 
107
{
 
108
        unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
 
109
        if (pending & STATUSF_IP2)
 
110
                do_IRQ(2);
 
111
        else if (pending & STATUSF_IP3)
 
112
                do_IRQ(3);
 
113
        else
 
114
                spurious_interrupt();
 
115
}
 
116
 
 
117
void jz4740_intc_suspend(void)
 
118
{
 
119
        jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
 
120
        writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
 
121
        writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
 
122
}
 
123
 
 
124
void jz4740_intc_resume(void)
 
125
{
 
126
        writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
 
127
        writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
 
128
}
 
129
 
 
130
#ifdef CONFIG_DEBUG_FS
 
131
 
 
132
static inline void intc_seq_reg(struct seq_file *s, const char *name,
 
133
        unsigned int reg)
 
134
{
 
135
        seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
 
136
}
 
137
 
 
138
static int intc_regs_show(struct seq_file *s, void *unused)
 
139
{
 
140
        intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
 
141
        intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
 
142
        intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
 
143
 
 
144
        return 0;
 
145
}
 
146
 
 
147
static int intc_regs_open(struct inode *inode, struct file *file)
 
148
{
 
149
        return single_open(file, intc_regs_show, NULL);
 
150
}
 
151
 
 
152
static const struct file_operations intc_regs_operations = {
 
153
        .open           = intc_regs_open,
 
154
        .read           = seq_read,
 
155
        .llseek         = seq_lseek,
 
156
        .release        = single_release,
 
157
};
 
158
 
 
159
static int __init intc_debugfs_init(void)
 
160
{
 
161
        (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
 
162
                                NULL, NULL, &intc_regs_operations);
 
163
        return 0;
 
164
}
 
165
subsys_initcall(intc_debugfs_init);
 
166
 
 
167
#endif