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
m68k
platform
coldfire
intc.c
Go to the documentation of this file.
1
/*
2
* intc.c -- support for the old ColdFire interrupt controller
3
*
4
* (C) Copyright 2009, Greg Ungerer <
[email protected]
>
5
*
6
* This file is subject to the terms and conditions of the GNU General Public
7
* License. See the file COPYING in the main directory of this archive
8
* for more details.
9
*/
10
11
#include <linux/types.h>
12
#include <
linux/init.h
>
13
#include <linux/kernel.h>
14
#include <
linux/interrupt.h
>
15
#include <
linux/irq.h
>
16
#include <
linux/io.h
>
17
#include <asm/traps.h>
18
#include <
asm/coldfire.h
>
19
#include <
asm/mcfsim.h
>
20
21
/*
22
* The mapping of irq number to a mask register bit is not one-to-one.
23
* The irq numbers are either based on "level" of interrupt or fixed
24
* for an autovector-able interrupt. So we keep a local data structure
25
* that maps from irq to mask register. Not all interrupts will have
26
* an IMR bit.
27
*/
28
unsigned
char
mcf_irq2imr
[
NR_IRQS
];
29
30
/*
31
* Define the miniumun and maximum external interrupt numbers.
32
* This is also used as the "level" interrupt numbers.
33
*/
34
#define EIRQ1 25
35
#define EIRQ7 31
36
37
/*
38
* In the early version 2 core ColdFire parts the IMR register was 16 bits
39
* in size. Version 3 (and later version 2) core parts have a 32 bit
40
* sized IMR register. Provide some size independent methods to access the
41
* IMR register.
42
*/
43
#ifdef MCFSIM_IMR_IS_16BITS
44
45
void
mcf_setimr
(
int
index
)
46
{
47
u16
imr
;
48
imr =
__raw_readw
(
MCFSIM_IMR
);
49
__raw_writew
(imr | (0x1 << index),
MCFSIM_IMR
);
50
}
51
52
void
mcf_clrimr
(
int
index
)
53
{
54
u16
imr
;
55
imr =
__raw_readw
(
MCFSIM_IMR
);
56
__raw_writew
(imr & ~(0x1 << index),
MCFSIM_IMR
);
57
}
58
59
void
mcf_maskimr
(
unsigned
int
mask
)
60
{
61
u16
imr
;
62
imr =
__raw_readw
(
MCFSIM_IMR
);
63
imr |=
mask
;
64
__raw_writew
(imr,
MCFSIM_IMR
);
65
}
66
67
#else
68
69
void
mcf_setimr
(
int
index)
70
{
71
u32
imr
;
72
imr =
__raw_readl
(
MCFSIM_IMR
);
73
__raw_writel
(imr | (0x1 << index),
MCFSIM_IMR
);
74
}
75
76
void
mcf_clrimr
(
int
index)
77
{
78
u32
imr
;
79
imr =
__raw_readl
(
MCFSIM_IMR
);
80
__raw_writel
(imr & ~(0x1 << index),
MCFSIM_IMR
);
81
}
82
83
void
mcf_maskimr
(
unsigned
int
mask
)
84
{
85
u32
imr
;
86
imr =
__raw_readl
(
MCFSIM_IMR
);
87
imr |=
mask
;
88
__raw_writel
(imr,
MCFSIM_IMR
);
89
}
90
91
#endif
92
93
/*
94
* Interrupts can be "vectored" on the ColdFire cores that support this old
95
* interrupt controller. That is, the device raising the interrupt can also
96
* supply the vector number to interrupt through. The AVR register of the
97
* interrupt controller enables or disables this for each external interrupt,
98
* so provide generic support for this. Setting this up is out-of-band for
99
* the interrupt system API's, and needs to be done by the driver that
100
* supports this device. Very few devices actually use this.
101
*/
102
void
mcf_autovector
(
int
irq)
103
{
104
#ifdef MCFSIM_AVR
105
if
((irq >=
EIRQ1
) && (irq <=
EIRQ7
)) {
106
u8
avec;
107
avec =
__raw_readb
(
MCFSIM_AVR
);
108
avec |= (0x1 << (irq -
EIRQ1
+ 1));
109
__raw_writeb
(avec,
MCFSIM_AVR
);
110
}
111
#endif
112
}
113
114
static
void
intc_irq_mask(
struct
irq_data
*
d
)
115
{
116
if
(
mcf_irq2imr
[d->
irq
])
117
mcf_setimr
(
mcf_irq2imr
[d->
irq
]);
118
}
119
120
static
void
intc_irq_unmask(
struct
irq_data
*d)
121
{
122
if
(
mcf_irq2imr
[d->
irq
])
123
mcf_clrimr
(
mcf_irq2imr
[d->
irq
]);
124
}
125
126
static
int
intc_irq_set_type(
struct
irq_data
*d,
unsigned
int
type
)
127
{
128
return
0;
129
}
130
131
static
struct
irq_chip
intc_irq_chip = {
132
.name =
"CF-INTC"
,
133
.irq_mask = intc_irq_mask,
134
.irq_unmask = intc_irq_unmask,
135
.irq_set_type = intc_irq_set_type,
136
};
137
138
void
__init
init_IRQ
(
void
)
139
{
140
int
irq
;
141
142
mcf_maskimr
(0xffffffff);
143
144
for
(irq = 0; (irq <
NR_IRQS
); irq++) {
145
irq_set_chip
(irq, &intc_irq_chip);
146
irq_set_irq_type
(irq,
IRQ_TYPE_LEVEL_HIGH
);
147
irq_set_handler(irq,
handle_level_irq
);
148
}
149
}
150
Generated on Thu Jan 10 2013 13:03:53 for Linux Kernel by
1.8.2