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
drivers
sh
intc
access.c
Go to the documentation of this file.
1
/*
2
* Common INTC2 register accessors
3
*
4
* Copyright (C) 2007, 2008 Magnus Damm
5
* Copyright (C) 2009, 2010 Paul Mundt
6
*
7
* This file is subject to the terms and conditions of the GNU General Public
8
* License. See the file "COPYING" in the main directory of this archive
9
* for more details.
10
*/
11
#include <
linux/io.h
>
12
#include "
internals.h
"
13
14
unsigned
long
intc_phys_to_virt
(
struct
intc_desc_int
*
d
,
unsigned
long
address
)
15
{
16
struct
intc_window
*
window
;
17
int
k
;
18
19
/* scan through physical windows and convert address */
20
for
(k = 0; k < d->
nr_windows
; k++) {
21
window = d->
window
+
k
;
22
23
if
(
address < window->
phys
)
24
continue
;
25
26
if
(address >= (window->
phys
+ window->
size
))
27
continue
;
28
29
address -= window->
phys
;
30
address += (
unsigned
long
)window->
virt
;
31
32
return
address;
33
}
34
35
/* no windows defined, register must be 1:1 mapped virt:phys */
36
return
address
;
37
}
38
39
unsigned
int
intc_get_reg
(
struct
intc_desc_int
*
d
,
unsigned
long
address
)
40
{
41
unsigned
int
k
;
42
43
address =
intc_phys_to_virt
(d, address);
44
45
for
(k = 0; k < d->
nr_reg
; k++) {
46
if
(d->
reg
[k] == address)
47
return
k
;
48
}
49
50
BUG
();
51
return
0;
52
}
53
54
unsigned
int
intc_set_field_from_handle
(
unsigned
int
value
,
55
unsigned
int
field_value,
56
unsigned
int
handle
)
57
{
58
unsigned
int
width
=
_INTC_WIDTH
(handle);
59
unsigned
int
shift =
_INTC_SHIFT
(handle);
60
61
value &= ~(((1 <<
width
) - 1) << shift);
62
value |= field_value << shift;
63
return
value
;
64
}
65
66
unsigned
long
intc_get_field_from_handle
(
unsigned
int
value
,
unsigned
int
handle
)
67
{
68
unsigned
int
width
=
_INTC_WIDTH
(handle);
69
unsigned
int
shift =
_INTC_SHIFT
(handle);
70
unsigned
int
mask
= ((1 <<
width
) - 1) << shift;
71
72
return
(value & mask) >> shift;
73
}
74
75
static
unsigned
long
test_8(
unsigned
long
addr
,
unsigned
long
h
,
76
unsigned
long
ignore)
77
{
78
void
__iomem
*
ptr
= (
void
__iomem
*)addr;
79
return
intc_get_field_from_handle
(
__raw_readb
(ptr), h);
80
}
81
82
static
unsigned
long
test_16(
unsigned
long
addr,
unsigned
long
h,
83
unsigned
long
ignore)
84
{
85
void
__iomem
*ptr = (
void
__iomem
*)addr;
86
return
intc_get_field_from_handle
(
__raw_readw
(ptr), h);
87
}
88
89
static
unsigned
long
test_32(
unsigned
long
addr,
unsigned
long
h,
90
unsigned
long
ignore)
91
{
92
void
__iomem
*ptr = (
void
__iomem
*)addr;
93
return
intc_get_field_from_handle
(
__raw_readl
(ptr), h);
94
}
95
96
static
unsigned
long
write_8(
unsigned
long
addr,
unsigned
long
h,
97
unsigned
long
data
)
98
{
99
void
__iomem
*ptr = (
void
__iomem
*)addr;
100
__raw_writeb
(
intc_set_field_from_handle
(0, data, h), ptr);
101
(
void
)
__raw_readb
(ptr);
/* Defeat write posting */
102
return
0;
103
}
104
105
static
unsigned
long
write_16(
unsigned
long
addr,
unsigned
long
h,
106
unsigned
long
data)
107
{
108
void
__iomem
*ptr = (
void
__iomem
*)addr;
109
__raw_writew
(
intc_set_field_from_handle
(0, data, h), ptr);
110
(
void
)
__raw_readw
(ptr);
/* Defeat write posting */
111
return
0;
112
}
113
114
static
unsigned
long
write_32(
unsigned
long
addr,
unsigned
long
h,
115
unsigned
long
data)
116
{
117
void
__iomem
*ptr = (
void
__iomem
*)addr;
118
__raw_writel
(
intc_set_field_from_handle
(0, data, h), ptr);
119
(
void
)
__raw_readl
(ptr);
/* Defeat write posting */
120
return
0;
121
}
122
123
static
unsigned
long
modify_8(
unsigned
long
addr,
unsigned
long
h,
124
unsigned
long
data)
125
{
126
void
__iomem
*ptr = (
void
__iomem
*)addr;
127
unsigned
long
flags
;
128
unsigned
int
value
;
129
local_irq_save
(flags);
130
value =
intc_set_field_from_handle
(
__raw_readb
(ptr), data, h);
131
__raw_writeb
(value, ptr);
132
(
void
)
__raw_readb
(ptr);
/* Defeat write posting */
133
local_irq_restore
(flags);
134
return
0;
135
}
136
137
static
unsigned
long
modify_16(
unsigned
long
addr,
unsigned
long
h,
138
unsigned
long
data)
139
{
140
void
__iomem
*ptr = (
void
__iomem
*)addr;
141
unsigned
long
flags
;
142
unsigned
int
value
;
143
local_irq_save
(flags);
144
value =
intc_set_field_from_handle
(
__raw_readw
(ptr), data, h);
145
__raw_writew
(value, ptr);
146
(
void
)
__raw_readw
(ptr);
/* Defeat write posting */
147
local_irq_restore
(flags);
148
return
0;
149
}
150
151
static
unsigned
long
modify_32(
unsigned
long
addr,
unsigned
long
h,
152
unsigned
long
data)
153
{
154
void
__iomem
*ptr = (
void
__iomem
*)addr;
155
unsigned
long
flags
;
156
unsigned
int
value
;
157
local_irq_save
(flags);
158
value =
intc_set_field_from_handle
(
__raw_readl
(ptr), data, h);
159
__raw_writel
(value, ptr);
160
(
void
)
__raw_readl
(ptr);
/* Defeat write posting */
161
local_irq_restore
(flags);
162
return
0;
163
}
164
165
static
unsigned
long
intc_mode_field(
unsigned
long
addr,
166
unsigned
long
handle
,
167
unsigned
long
(*
fn
)(
unsigned
long
,
168
unsigned
long
,
169
unsigned
long
),
170
unsigned
int
irq)
171
{
172
return
fn
(addr, handle, ((1 <<
_INTC_WIDTH
(handle)) - 1));
173
}
174
175
static
unsigned
long
intc_mode_zero(
unsigned
long
addr,
176
unsigned
long
handle,
177
unsigned
long
(*
fn
)(
unsigned
long
,
178
unsigned
long
,
179
unsigned
long
),
180
unsigned
int
irq)
181
{
182
return
fn
(addr, handle, 0);
183
}
184
185
static
unsigned
long
intc_mode_prio(
unsigned
long
addr,
186
unsigned
long
handle,
187
unsigned
long
(*
fn
)(
unsigned
long
,
188
unsigned
long
,
189
unsigned
long
),
190
unsigned
int
irq)
191
{
192
return
fn
(addr, handle,
intc_get_prio_level
(irq));
193
}
194
195
unsigned
long
(*
intc_reg_fns
[])(
unsigned
long
addr
,
196
unsigned
long
h
,
197
unsigned
long
data
) = {
198
[
REG_FN_TEST_BASE
+ 0] = test_8,
199
[
REG_FN_TEST_BASE
+ 1] = test_16,
200
[
REG_FN_TEST_BASE
+ 3] = test_32,
201
[
REG_FN_WRITE_BASE
+ 0] = write_8,
202
[
REG_FN_WRITE_BASE
+ 1] = write_16,
203
[
REG_FN_WRITE_BASE
+ 3] = write_32,
204
[
REG_FN_MODIFY_BASE
+ 0] = modify_8,
205
[
REG_FN_MODIFY_BASE
+ 1] = modify_16,
206
[
REG_FN_MODIFY_BASE
+ 3] = modify_32,
207
};
208
209
unsigned
long
(*
intc_enable_fns
[])(
unsigned
long
addr
,
210
unsigned
long
handle
,
211
unsigned
long
(*
fn
)(
unsigned
long
,
212
unsigned
long
,
213
unsigned
long
),
214
unsigned
int
irq) = {
215
[
MODE_ENABLE_REG
] = intc_mode_field,
216
[
MODE_MASK_REG
] = intc_mode_zero,
217
[
MODE_DUAL_REG
] = intc_mode_field,
218
[
MODE_PRIO_REG
] = intc_mode_prio,
219
[
MODE_PCLR_REG
] = intc_mode_prio,
220
};
221
222
unsigned
long
(*
intc_disable_fns
[])(
unsigned
long
addr
,
223
unsigned
long
handle
,
224
unsigned
long
(*
fn
)(
unsigned
long
,
225
unsigned
long
,
226
unsigned
long
),
227
unsigned
int
irq) = {
228
[
MODE_ENABLE_REG
] = intc_mode_zero,
229
[
MODE_MASK_REG
] = intc_mode_field,
230
[
MODE_DUAL_REG
] = intc_mode_field,
231
[
MODE_PRIO_REG
] = intc_mode_zero,
232
[
MODE_PCLR_REG
] = intc_mode_field,
233
};
234
235
unsigned
long
(*
intc_enable_noprio_fns
[])(
unsigned
long
addr
,
236
unsigned
long
handle
,
237
unsigned
long
(*
fn
)(
unsigned
long
,
238
unsigned
long
,
239
unsigned
long
),
240
unsigned
int
irq) = {
241
[
MODE_ENABLE_REG
] = intc_mode_field,
242
[
MODE_MASK_REG
] = intc_mode_zero,
243
[
MODE_DUAL_REG
] = intc_mode_field,
244
[
MODE_PRIO_REG
] = intc_mode_field,
245
[
MODE_PCLR_REG
] = intc_mode_field,
246
};
Generated on Thu Jan 10 2013 14:13:59 for Linux Kernel by
1.8.2