Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c5760066
Commit
c5760066
authored
Jun 25, 2003
by
Anton Blanchard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ppc64: merge Paul's interrupt-map parsing code
parent
a7872552
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
172 additions
and
124 deletions
+172
-124
arch/ppc64/kernel/prom.c
arch/ppc64/kernel/prom.c
+172
-124
No files found.
arch/ppc64/kernel/prom.c
View file @
c5760066
...
...
@@ -1538,137 +1538,185 @@ finish_node(struct device_node *np, unsigned long mem_start,
return
mem_start
;
}
/* This routine walks the interrupt tree for a given device node and gather
* all necessary informations according to the draft interrupt mapping
* for CHRP. The current version was only tested on Apple "Core99" machines
* and may not handle cascaded controllers correctly.
/*
* Find the interrupt parent of a node.
*/
__init
static
unsigned
long
finish_node_interrupts
(
struct
device_node
*
np
,
unsigned
long
mem_start
)
static
struct
device_node
*
__init
intr_parent
(
struct
device_node
*
p
)
{
/* Finish this node */
unsigned
int
*
isizep
,
*
asizep
,
*
interrupts
,
*
map
,
*
map_mask
,
*
reg
;
phandle
*
parent
,
map_parent
;
struct
device_node
*
node
,
*
parent_node
;
int
l
,
isize
,
ipsize
,
asize
,
map_size
,
regpsize
;
/* Currently, we don't look at all nodes with no "interrupts" property */
phandle
*
parp
;
interrupts
=
(
unsigned
int
*
)
get_property
(
np
,
"interrupts"
,
&
l
);
if
(
interrupts
==
NULL
)
return
mem_start
;
ipsize
=
l
>>
2
;
parp
=
(
phandle
*
)
get_property
(
p
,
"interrupt-parent"
,
NULL
);
if
(
parp
==
NULL
)
return
p
->
parent
;
return
find_phandle
(
*
parp
);
}
reg
=
(
unsigned
int
*
)
get_property
(
np
,
"reg"
,
&
l
);
regpsize
=
l
>>
2
;
/*
* Find out the size of each entry of the interrupts property
* for a node.
*/
static
int
__init
prom_n_intr_cells
(
struct
device_node
*
np
)
{
struct
device_node
*
p
;
unsigned
int
*
icp
;
for
(
p
=
np
;
(
p
=
intr_parent
(
p
))
!=
NULL
;
)
{
icp
=
(
unsigned
int
*
)
get_property
(
p
,
"#interrupt-cells"
,
NULL
);
if
(
icp
!=
NULL
)
return
*
icp
;
if
(
get_property
(
p
,
"interrupt-controller"
,
NULL
)
!=
NULL
||
get_property
(
p
,
"interrupt-map"
,
NULL
)
!=
NULL
)
{
printk
(
"oops, node %s doesn't have #interrupt-cells
\n
"
,
p
->
full_name
);
return
1
;
}
}
#ifdef DEBUG_IRQ
printk
(
"prom_n_intr_cells failed for %s
\n
"
,
np
->
full_name
);
#endif
return
1
;
}
/* We assume default interrupt cell size is 1 (bugus ?) */
isize
=
1
;
node
=
np
;
do
{
/* We adjust the cell size if the current parent contains an #interrupt-cells
* property */
isizep
=
(
unsigned
int
*
)
get_property
(
node
,
"#interrupt-cells"
,
&
l
);
if
(
isizep
)
isize
=
*
isizep
;
/* We don't do interrupt cascade (ISA) for now, we stop on the first
* controller found
*/
if
(
get_property
(
node
,
"interrupt-controller"
,
&
l
))
{
int
i
,
j
;
np
->
intrs
=
(
struct
interrupt_info
*
)
mem_start
;
np
->
n_intrs
=
ipsize
/
isize
;
mem_start
+=
np
->
n_intrs
*
sizeof
(
struct
interrupt_info
);
for
(
i
=
0
;
i
<
np
->
n_intrs
;
++
i
)
{
np
->
intrs
[
i
].
line
=
openpic_to_irq
(
virt_irq_create_mapping
(
*
interrupts
++
));
np
->
intrs
[
i
].
sense
=
1
;
if
(
isize
>
1
)
np
->
intrs
[
i
].
sense
=
*
interrupts
++
;
for
(
j
=
2
;
j
<
isize
;
j
++
)
interrupts
++
;
/*
* Map an interrupt from a device up to the platform interrupt
* descriptor.
*/
static
int
__init
map_interrupt
(
unsigned
int
**
irq
,
struct
device_node
**
ictrler
,
struct
device_node
*
np
,
unsigned
int
*
ints
,
int
nintrc
)
{
struct
device_node
*
p
,
*
ipar
;
unsigned
int
*
imap
,
*
imask
,
*
ip
;
int
i
,
imaplen
,
match
;
int
newintrc
,
newaddrc
;
unsigned
int
*
reg
;
int
naddrc
;
reg
=
(
unsigned
int
*
)
get_property
(
np
,
"reg"
,
NULL
);
naddrc
=
prom_n_addr_cells
(
np
);
p
=
intr_parent
(
np
);
while
(
p
!=
NULL
)
{
if
(
get_property
(
p
,
"interrupt-controller"
,
NULL
)
!=
NULL
)
/* this node is an interrupt controller, stop here */
break
;
imap
=
(
unsigned
int
*
)
get_property
(
p
,
"interrupt-map"
,
&
imaplen
);
if
(
imap
==
NULL
)
{
p
=
intr_parent
(
p
);
continue
;
}
imask
=
(
unsigned
int
*
)
get_property
(
p
,
"interrupt-map-mask"
,
NULL
);
if
(
imask
==
NULL
)
{
printk
(
"oops, %s has interrupt-map but no mask
\n
"
,
p
->
full_name
);
return
0
;
}
imaplen
/=
sizeof
(
unsigned
int
);
match
=
0
;
ipar
=
NULL
;
while
(
imaplen
>
0
&&
!
match
)
{
/* check the child-interrupt field */
match
=
1
;
for
(
i
=
0
;
i
<
naddrc
&&
match
;
++
i
)
match
=
((
reg
[
i
]
^
imap
[
i
])
&
imask
[
i
])
==
0
;
for
(;
i
<
naddrc
+
nintrc
&&
match
;
++
i
)
match
=
((
ints
[
i
-
naddrc
]
^
imap
[
i
])
&
imask
[
i
])
==
0
;
imap
+=
naddrc
+
nintrc
;
imaplen
-=
naddrc
+
nintrc
;
/* grab the interrupt parent */
ipar
=
find_phandle
((
phandle
)
*
imap
++
);
--
imaplen
;
if
(
ipar
==
NULL
)
{
printk
(
"oops, no int parent %x in map of %s
\n
"
,
imap
[
-
1
],
p
->
full_name
);
return
0
;
}
/* find the parent's # addr and intr cells */
ip
=
(
unsigned
int
*
)
get_property
(
ipar
,
"#interrupt-cells"
,
NULL
);
if
(
ip
==
NULL
)
{
printk
(
"oops, no #interrupt-cells on %s
\n
"
,
ipar
->
full_name
);
return
0
;
}
newintrc
=
*
ip
;
ip
=
(
unsigned
int
*
)
get_property
(
ipar
,
"#address-cells"
,
NULL
);
newaddrc
=
(
ip
==
NULL
)
?
0
:
*
ip
;
imap
+=
newaddrc
+
newintrc
;
imaplen
-=
newaddrc
+
newintrc
;
}
if
(
imaplen
<
0
)
{
printk
(
"oops, error decoding int-map on %s, len=%d
\n
"
,
p
->
full_name
,
imaplen
);
return
0
;
}
if
(
!
match
)
{
#ifdef DEBUG_IRQ
printk
(
"oops, no match in %s int-map for %s
\n
"
,
p
->
full_name
,
np
->
full_name
);
#endif
return
0
;
}
p
=
ipar
;
naddrc
=
newaddrc
;
nintrc
=
newintrc
;
ints
=
imap
-
nintrc
;
reg
=
ints
-
naddrc
;
}
#ifdef DEBUG_IRQ
if
(
p
==
NULL
)
printk
(
"hmmm, int tree for %s doesn't have ctrler
\n
"
,
np
->
full_name
);
#endif
*
irq
=
ints
;
*
ictrler
=
p
;
return
nintrc
;
}
/*
* New version of finish_node_interrupts.
*/
static
unsigned
long
__init
finish_node_interrupts
(
struct
device_node
*
np
,
unsigned
long
mem_start
)
{
unsigned
int
*
ints
;
int
intlen
,
intrcells
;
int
i
,
j
,
n
;
unsigned
int
*
irq
;
struct
device_node
*
ic
;
ints
=
(
unsigned
int
*
)
get_property
(
np
,
"interrupts"
,
&
intlen
);
if
(
ints
==
NULL
)
return
mem_start
;
}
/* We lookup for an interrupt-map. This code can only handle one interrupt
* per device in the map. We also don't handle #address-cells in the parent
* I skip the pci node itself here, may not be necessary but I don't like it's
* reg property.
*/
if
(
np
!=
node
)
map
=
(
unsigned
int
*
)
get_property
(
node
,
"interrupt-map"
,
&
l
);
else
map
=
NULL
;
if
(
map
&&
l
)
{
int
i
,
found
,
temp_isize
,
temp_asize
;
map_size
=
l
>>
2
;
map_mask
=
(
unsigned
int
*
)
get_property
(
node
,
"interrupt-map-mask"
,
&
l
);
asizep
=
(
unsigned
int
*
)
get_property
(
node
,
"#address-cells"
,
&
l
);
if
(
asizep
&&
l
==
sizeof
(
unsigned
int
))
asize
=
*
asizep
;
else
asize
=
0
;
found
=
0
;
while
(
map_size
>
0
&&
!
found
)
{
found
=
1
;
for
(
i
=
0
;
i
<
asize
;
i
++
)
{
unsigned
int
mask
=
map_mask
?
map_mask
[
i
]
:
0xffffffff
;
if
(
!
reg
||
(
i
>=
regpsize
)
||
((
mask
&
*
map
)
!=
(
mask
&
reg
[
i
])))
found
=
0
;
map
++
;
map_size
--
;
}
for
(
i
=
0
;
i
<
isize
;
i
++
)
{
unsigned
int
mask
=
map_mask
?
map_mask
[
i
+
asize
]
:
0xffffffff
;
if
((
mask
&
*
map
)
!=
(
mask
&
interrupts
[
i
]))
found
=
0
;
map
++
;
map_size
--
;
}
map_parent
=
*
((
phandle
*
)
map
);
map
+=
1
;
map_size
-=
1
;
parent_node
=
find_phandle
(
map_parent
);
temp_isize
=
isize
;
temp_asize
=
0
;
if
(
parent_node
)
{
isizep
=
(
unsigned
int
*
)
get_property
(
parent_node
,
"#interrupt-cells"
,
&
l
);
if
(
isizep
)
temp_isize
=
*
isizep
;
asizep
=
(
unsigned
int
*
)
get_property
(
parent_node
,
"#address-cells"
,
&
l
);
if
(
asizep
&&
l
==
sizeof
(
unsigned
int
))
temp_asize
=
*
asizep
;
}
if
(
!
found
)
{
map
+=
temp_isize
+
temp_asize
;
map_size
-=
temp_isize
+
temp_asize
;
}
}
if
(
found
)
{
/* Mapped to a new parent. Use the reg and interrupts specified in
* the map as the new search parameters. Then search from the parent.
*/
node
=
parent_node
;
reg
=
map
;
regpsize
=
temp_asize
;
interrupts
=
map
+
temp_asize
;
ipsize
=
temp_isize
;
continue
;
}
}
/* We look for an explicit interrupt-parent.
*/
parent
=
(
phandle
*
)
get_property
(
node
,
"interrupt-parent"
,
&
l
);
if
(
parent
&&
(
l
==
sizeof
(
phandle
))
&&
(
parent_node
=
find_phandle
(
*
parent
)))
{
node
=
parent_node
;
continue
;
}
/* Default, get real parent */
node
=
node
->
parent
;
}
while
(
node
);
intrcells
=
prom_n_intr_cells
(
np
);
intlen
/=
intrcells
*
sizeof
(
unsigned
int
);
np
->
n_intrs
=
intlen
;
np
->
intrs
=
(
struct
interrupt_info
*
)
mem_start
;
mem_start
+=
intlen
*
sizeof
(
struct
interrupt_info
);
for
(
i
=
0
;
i
<
intlen
;
++
i
)
{
np
->
intrs
[
i
].
line
=
0
;
np
->
intrs
[
i
].
sense
=
1
;
n
=
map_interrupt
(
&
irq
,
&
ic
,
np
,
ints
,
intrcells
);
if
(
n
<=
0
)
continue
;
np
->
intrs
[
i
].
line
=
openpic_to_irq
(
virt_irq_create_mapping
(
irq
[
0
]));
if
(
n
>
1
)
np
->
intrs
[
i
].
sense
=
irq
[
1
];
if
(
n
>
2
)
{
printk
(
"hmmm, got %d intr cells for %s:"
,
n
,
np
->
full_name
);
for
(
j
=
0
;
j
<
n
;
++
j
)
printk
(
" %d"
,
irq
[
j
]);
printk
(
"
\n
"
);
}
ints
+=
intrcells
;
}
return
mem_start
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment