Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
mips
loongson1
common
irq.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Zhang, Keguang <
[email protected]
>
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
10
#include <
linux/interrupt.h
>
11
#include <
linux/irq.h
>
12
#include <
asm/irq_cpu.h
>
13
14
#include <
loongson1.h
>
15
#include <
irq.h
>
16
17
#define LS1X_INTC_REG(n, x) \
18
((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
19
20
#define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0)
21
#define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4)
22
#define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8)
23
#define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc)
24
#define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10)
25
#define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14)
26
27
static
void
ls1x_irq_ack(
struct
irq_data
*
d
)
28
{
29
unsigned
int
bit
= (d->
irq
-
LS1X_IRQ_BASE
) & 0x1f;
30
unsigned
int
n
= (d->
irq
-
LS1X_IRQ_BASE
) >> 5;
31
32
__raw_writel
(
__raw_readl
(
LS1X_INTC_INTCLR
(n))
33
| (1 << bit),
LS1X_INTC_INTCLR
(n));
34
}
35
36
static
void
ls1x_irq_mask(
struct
irq_data
*
d
)
37
{
38
unsigned
int
bit
= (d->
irq
-
LS1X_IRQ_BASE
) & 0x1f;
39
unsigned
int
n
= (d->
irq
-
LS1X_IRQ_BASE
) >> 5;
40
41
__raw_writel
(
__raw_readl
(
LS1X_INTC_INTIEN
(n))
42
& ~(1 << bit),
LS1X_INTC_INTIEN
(n));
43
}
44
45
static
void
ls1x_irq_mask_ack(
struct
irq_data
*d)
46
{
47
unsigned
int
bit = (d->
irq
-
LS1X_IRQ_BASE
) & 0x1f;
48
unsigned
int
n = (d->
irq
-
LS1X_IRQ_BASE
) >> 5;
49
50
__raw_writel
(
__raw_readl
(
LS1X_INTC_INTIEN
(n))
51
& ~(1 << bit),
LS1X_INTC_INTIEN
(n));
52
__raw_writel
(
__raw_readl
(
LS1X_INTC_INTCLR
(n))
53
| (1 << bit),
LS1X_INTC_INTCLR
(n));
54
}
55
56
static
void
ls1x_irq_unmask(
struct
irq_data
*d)
57
{
58
unsigned
int
bit = (d->
irq
-
LS1X_IRQ_BASE
) & 0x1f;
59
unsigned
int
n = (d->
irq
-
LS1X_IRQ_BASE
) >> 5;
60
61
__raw_writel
(
__raw_readl
(
LS1X_INTC_INTIEN
(n))
62
| (1 << bit),
LS1X_INTC_INTIEN
(n));
63
}
64
65
static
struct
irq_chip
ls1x_irq_chip = {
66
.name =
"LS1X-INTC"
,
67
.irq_ack = ls1x_irq_ack,
68
.irq_mask = ls1x_irq_mask,
69
.irq_mask_ack = ls1x_irq_mask_ack,
70
.irq_unmask = ls1x_irq_unmask,
71
};
72
73
static
void
ls1x_irq_dispatch(
int
n)
74
{
75
u32
int_status
,
irq
;
76
77
/* Get pending sources, masked by current enables */
78
int_status =
__raw_readl
(
LS1X_INTC_INTISR
(n)) &
79
__raw_readl
(
LS1X_INTC_INTIEN
(n));
80
81
if
(int_status) {
82
irq =
LS1X_IRQ
(n,
__ffs
(int_status));
83
do_IRQ
(irq);
84
}
85
}
86
87
asmlinkage
void
plat_irq_dispatch
(
void
)
88
{
89
unsigned
int
pending;
90
91
pending =
read_c0_cause
() &
read_c0_status
() &
ST0_IM
;
92
93
if
(pending &
CAUSEF_IP7
)
94
do_IRQ
(
TIMER_IRQ
);
95
else
if
(pending &
CAUSEF_IP2
)
96
ls1x_irq_dispatch(0);
/* INT0 */
97
else
if
(pending &
CAUSEF_IP3
)
98
ls1x_irq_dispatch(1);
/* INT1 */
99
else
if
(pending &
CAUSEF_IP4
)
100
ls1x_irq_dispatch(2);
/* INT2 */
101
else
if
(pending &
CAUSEF_IP5
)
102
ls1x_irq_dispatch(3);
/* INT3 */
103
else
if
(pending &
CAUSEF_IP6
)
104
ls1x_irq_dispatch(4);
/* INT4 */
105
else
106
spurious_interrupt
();
107
108
}
109
110
struct
irqaction
cascade_irqaction
= {
111
.handler =
no_action
,
112
.name =
"cascade"
,
113
.flags =
IRQF_NO_THREAD
,
114
};
115
116
static
void
__init
ls1x_irq_init(
int
base)
117
{
118
int
n
;
119
120
/* Disable interrupts and clear pending,
121
* setup all IRQs as high level triggered
122
*/
123
for
(n = 0; n < 4; n++) {
124
__raw_writel
(0x0,
LS1X_INTC_INTIEN
(n));
125
__raw_writel
(0xffffffff,
LS1X_INTC_INTCLR
(n));
126
__raw_writel
(0xffffffff,
LS1X_INTC_INTPOL
(n));
127
/* set DMA0, DMA1 and DMA2 to edge trigger */
128
__raw_writel
(n ? 0x0 : 0xe000,
LS1X_INTC_INTEDGE
(n));
129
}
130
131
132
for
(n = base; n <
LS1X_IRQS
; n++) {
133
irq_set_chip_and_handler(n, &ls1x_irq_chip,
134
handle_level_irq
);
135
}
136
137
setup_irq
(
INT0_IRQ
, &cascade_irqaction);
138
setup_irq
(
INT1_IRQ
, &cascade_irqaction);
139
setup_irq
(
INT2_IRQ
, &cascade_irqaction);
140
setup_irq
(
INT3_IRQ
, &cascade_irqaction);
141
}
142
143
void
__init
arch_init_irq
(
void
)
144
{
145
mips_cpu_irq_init
();
146
ls1x_irq_init(
LS1X_IRQ_BASE
);
147
}
Generated on Thu Jan 10 2013 12:51:29 for Linux Kernel by
1.8.2