~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to arch/mips/kernel/irq-rm9000.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003 Ralf Baechle
 
3
 *
 
4
 * This program is free software; you can redistribute  it and/or modify it
 
5
 * under  the terms of  the GNU General  Public License as published by the
 
6
 * Free Software Foundation;  either version 2 of the  License, or (at your
 
7
 * option) any later version.
 
8
 *
 
9
 * Handler for RM9000 extended interrupts.  These are a non-standard
 
10
 * feature so we handle them separately from standard interrupts.
 
11
 */
 
12
#include <linux/init.h>
 
13
#include <linux/interrupt.h>
 
14
#include <linux/kernel.h>
 
15
#include <linux/module.h>
 
16
 
 
17
#include <asm/irq_cpu.h>
 
18
#include <asm/mipsregs.h>
 
19
#include <asm/system.h>
 
20
 
 
21
static inline void unmask_rm9k_irq(unsigned int irq)
 
22
{
 
23
        set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 
24
}
 
25
 
 
26
static inline void mask_rm9k_irq(unsigned int irq)
 
27
{
 
28
        clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 
29
}
 
30
 
 
31
static inline void rm9k_cpu_irq_enable(unsigned int irq)
 
32
{
 
33
        unsigned long flags;
 
34
 
 
35
        local_irq_save(flags);
 
36
        unmask_rm9k_irq(irq);
 
37
        local_irq_restore(flags);
 
38
}
 
39
 
 
40
/*
 
41
 * Performance counter interrupts are global on all processors.
 
42
 */
 
43
static void local_rm9k_perfcounter_irq_startup(void *args)
 
44
{
 
45
        unsigned int irq = (unsigned int) args;
 
46
 
 
47
        rm9k_cpu_irq_enable(irq);
 
48
}
 
49
 
 
50
static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq)
 
51
{
 
52
        on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 1);
 
53
 
 
54
        return 0;
 
55
}
 
56
 
 
57
static void local_rm9k_perfcounter_irq_shutdown(void *args)
 
58
{
 
59
        unsigned int irq = (unsigned int) args;
 
60
        unsigned long flags;
 
61
 
 
62
        local_irq_save(flags);
 
63
        mask_rm9k_irq(irq);
 
64
        local_irq_restore(flags);
 
65
}
 
66
 
 
67
static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
 
68
{
 
69
        on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 1);
 
70
}
 
71
 
 
72
static struct irq_chip rm9k_irq_controller = {
 
73
        .name = "RM9000",
 
74
        .ack = mask_rm9k_irq,
 
75
        .mask = mask_rm9k_irq,
 
76
        .mask_ack = mask_rm9k_irq,
 
77
        .unmask = unmask_rm9k_irq,
 
78
        .eoi    = unmask_rm9k_irq
 
79
};
 
80
 
 
81
static struct irq_chip rm9k_perfcounter_irq = {
 
82
        .name = "RM9000",
 
83
        .startup = rm9k_perfcounter_irq_startup,
 
84
        .shutdown = rm9k_perfcounter_irq_shutdown,
 
85
        .ack = mask_rm9k_irq,
 
86
        .mask = mask_rm9k_irq,
 
87
        .mask_ack = mask_rm9k_irq,
 
88
        .unmask = unmask_rm9k_irq,
 
89
};
 
90
 
 
91
unsigned int rm9000_perfcount_irq;
 
92
 
 
93
EXPORT_SYMBOL(rm9000_perfcount_irq);
 
94
 
 
95
void __init rm9k_cpu_irq_init(void)
 
96
{
 
97
        int base = RM9K_CPU_IRQ_BASE;
 
98
        int i;
 
99
 
 
100
        clear_c0_intcontrol(0x0000f000);                /* Mask all */
 
101
 
 
102
        for (i = base; i < base + 4; i++)
 
103
                set_irq_chip_and_handler(i, &rm9k_irq_controller,
 
104
                                         handle_level_irq);
 
105
 
 
106
        rm9000_perfcount_irq = base + 1;
 
107
        set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
 
108
                                 handle_percpu_irq);
 
109
}