Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
69c010b2
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
69c010b2
编写于
9月 19, 2008
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
sparc32: Use PROM device probing for sun4m irq registers.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
2e57572a
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
74 addition
and
129 deletion
+74
-129
arch/sparc/kernel/entry.S
arch/sparc/kernel/entry.S
+20
-20
arch/sparc/kernel/sun4m_irq.c
arch/sparc/kernel/sun4m_irq.c
+54
-109
未找到文件。
arch/sparc/kernel/entry.S
浏览文件 @
69c010b2
...
...
@@ -272,17 +272,18 @@ smp4m_ticker:
*/
maybe_smp4m_msg
:
GET_PROCESSOR4M_ID
(
o3
)
set
sun4m_interrupts
,
%
l5
ld
[%
l5
],
%
o5
sethi
%
hi
(
sun4m_irq_percpu
),
%
l5
sll
%
o3
,
2
,
%
o3
or
%
l5
,
%
lo
(
sun4m_irq_percpu
),
%
o5
sethi
%
hi
(
0x40000000
),
%
o2
sll
%
o3
,
12
,
%
o3
ld
[%
o5
+
%
o3
],
%
o1
andcc
%
o1
,
%
o2
,
%
g0
ld
[%
o1
+
0x00
],
%
o3
!
sun4m_irq_percpu
[
cpu
]->
pending
andcc
%
o3
,
%
o2
,
%
g0
be
,
a
smp4m_ticker
cmp
%
l7
,
14
st
%
o2
,
[%
o
5
+
0x4
]
st
%
o2
,
[%
o
1
+
0x04
]
!
sun4m_irq_percpu
[
cpu
]->
clear
=
0x40000000
WRITE_PAUSE
ld
[%
o
5
],
%
g0
ld
[%
o
1
+
0x00
],
%
g0
!
sun4m_irq_percpu
[
cpu
]->
pending
WRITE_PAUSE
or
%
l0
,
PSR_PIL
,
%
l4
wr
%
l4
,
0x0
,
%
psr
...
...
@@ -300,16 +301,16 @@ linux_trap_ipi15_sun4m:
SAVE_ALL
sethi
%
hi
(
0x80000000
),
%
o2
GET_PROCESSOR4M_ID
(
o0
)
set
sun4m_interrupts
,
%
l5
ld
[%
l5
]
,
%
o5
sll
%
o0
,
1
2
,
%
o0
add
%
o5
,
%
o0
,
%
o5
ld
[%
o5
],
%
o3
set
hi
%
hi
(
sun4m_irq_percpu
)
,
%
l5
or
%
l5
,
%
lo
(
sun4m_irq_percpu
)
,
%
o5
sll
%
o0
,
2
,
%
o0
ld
[%
o5
+
%
o0
]
,
%
o5
ld
[%
o5
+
0x00
],
%
o3
!
sun4m_irq_percpu
[
cpu
]->
pending
andcc
%
o3
,
%
o2
,
%
g0
be
1
f
!
Must
be
an
NMI
async
memory
error
st
%
o2
,
[%
o5
+
4
]
st
%
o2
,
[%
o5
+
0x04
]
!
sun4m_irq_percpu
[
cpu
]->
clear
=
0x80000000
WRITE_PAUSE
ld
[%
o5
],
%
g0
ld
[%
o5
+
0x00
],
%
g0
!
sun4m_irq_percpu
[
cpu
]->
pending
WRITE_PAUSE
or
%
l0
,
PSR_PIL
,
%
l4
wr
%
l4
,
0x0
,
%
psr
...
...
@@ -323,12 +324,11 @@ linux_trap_ipi15_sun4m:
1
:
/
*
NMI
async
memory
error
handling
.
*/
sethi
%
hi
(
0x80000000
),
%
l4
sethi
%
hi
(
0x4000
),
%
o3
sub
%
o5
,
%
o0
,
%
o5
add
%
o5
,
%
o3
,
%
l5
st
%
l4
,
[%
l5
+
0xc
]
sethi
%
hi
(
sun4m_irq_global
),
%
o5
ld
[%
o5
+
%
lo
(
sun4m_irq_global
)],
%
l5
st
%
l4
,
[%
l5
+
0x0c
]
!
sun4m_irq_global
->
mask_set
=
0x80000000
WRITE_PAUSE
ld
[%
l5
],
%
g0
ld
[%
l5
+
0x00
],
%
g0
!
sun4m_irq_global
->
pending
WRITE_PAUSE
or
%
l0
,
PSR_PIL
,
%
l4
wr
%
l4
,
0x0
,
%
psr
...
...
@@ -337,9 +337,9 @@ linux_trap_ipi15_sun4m:
WRITE_PAUSE
call
sun4m_nmi
nop
st
%
l4
,
[%
l5
+
0x
8
]
st
%
l4
,
[%
l5
+
0x
08
]
!
sun4m_irq_global
->
mask_clear
=
0x80000000
WRITE_PAUSE
ld
[%
l5
],
%
g0
ld
[%
l5
+
0x00
],
%
g0
!
sun4m_irq_global
->
pending
WRITE_PAUSE
RESTORE_ALL
...
...
arch/sparc/kernel/sun4m_irq.c
浏览文件 @
69c010b2
...
...
@@ -41,53 +41,25 @@
#include "irq.h"
/* On the sun4m, just like the timers, we have both per-cpu and master
* interrupt registers.
*/
/* These registers are used for sending/receiving irqs from/to
* different cpu's.
*/
struct
sun4m_intreg_percpu
{
unsigned
int
tbt
;
/* Interrupts still pending for this cpu. */
/* These next two registers are WRITE-ONLY and are only
* "on bit" sensitive, "off bits" written have NO affect.
*/
unsigned
int
clear
;
/* Clear this cpus irqs here. */
unsigned
int
set
;
/* Set this cpus irqs here. */
unsigned
char
space
[
PAGE_SIZE
-
12
];
struct
sun4m_irq_percpu
{
u32
pending
;
u32
clear
;
u32
set
;
};
/*
* djhr
* Actually the clear and set fields in this struct are misleading..
* according to the SLAVIO manual (and the same applies for the SEC)
* the clear field clears bits in the mask which will ENABLE that IRQ
* the set field sets bits in the mask to DISABLE the IRQ.
*
* Also the undirected_xx address in the SLAVIO is defined as
* RESERVED and write only..
*
* DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
* sun4m machines, for MP the layout makes more sense.
*/
struct
sun4m_intregs
{
struct
sun4m_intreg_percpu
cpu_intregs
[
SUN4M_NCPUS
];
unsigned
int
tbt
;
/* IRQ's that are still pending. */
unsigned
int
irqs
;
/* Master IRQ bits. */
/* Again, like the above, two these registers are WRITE-ONLY. */
unsigned
int
clear
;
/* Clear master IRQ's by setting bits here. */
unsigned
int
set
;
/* Set master IRQ's by setting bits here. */
/* This register is both READ and WRITE. */
unsigned
int
undirected_target
;
/* Which cpu gets undirected irqs. */
struct
sun4m_irq_global
{
u32
pending
;
u32
mask
;
u32
mask_clear
;
u32
mask_set
;
u32
interrupt_target
;
};
static
unsigned
long
dummy
;
/* Code in entry.S needs to get at these register mappings. */
struct
sun4m_irq_percpu
__iomem
*
sun4m_irq_percpu
[
SUN4M_NCPUS
];
struct
sun4m_irq_global
__iomem
*
sun4m_irq_global
;
st
ruct
sun4m_intregs
*
sun4m_interrupts
;
st
atic
unsigned
long
dummy
;
unsigned
long
*
irq_rcvreg
=
&
dummy
;
/* Dave Redman (djhr@tadpole.co.uk)
...
...
@@ -182,9 +154,9 @@ static void sun4m_disable_irq(unsigned int irq_nr)
mask
=
sun4m_get_irqmask
(
irq_nr
);
local_irq_save
(
flags
);
if
(
irq_nr
>
15
)
s
un4m_interrupts
->
set
=
mask
;
s
bus_writel
(
mask
,
&
sun4m_irq_global
->
mask_set
)
;
else
s
un4m_interrupts
->
cpu_intregs
[
cpu
].
set
=
mask
;
s
bus_writel
(
mask
,
&
sun4m_irq_percpu
[
cpu
]
->
set
)
;
local_irq_restore
(
flags
);
}
...
...
@@ -201,13 +173,13 @@ static void sun4m_enable_irq(unsigned int irq_nr)
mask
=
sun4m_get_irqmask
(
irq_nr
);
local_irq_save
(
flags
);
if
(
irq_nr
>
15
)
s
un4m_interrupts
->
clear
=
mask
;
s
bus_writel
(
mask
,
&
sun4m_irq_global
->
mask_clear
)
;
else
s
un4m_interrupts
->
cpu_intregs
[
cpu
].
clear
=
mask
;
s
bus_writel
(
mask
,
&
sun4m_irq_percpu
[
cpu
]
->
clear
)
;
local_irq_restore
(
flags
);
}
else
{
local_irq_save
(
flags
);
s
un4m_interrupts
->
clear
=
SUN4M_INT_FLOPPY
;
s
bus_writel
(
SUN4M_INT_FLOPPY
,
&
sun4m_irq_global
->
mask_clear
)
;
local_irq_restore
(
flags
);
}
}
...
...
@@ -236,34 +208,30 @@ static unsigned long cpu_pil_to_imask[16] = {
*/
static
void
sun4m_disable_pil_irq
(
unsigned
int
pil
)
{
s
un4m_interrupts
->
set
=
cpu_pil_to_imask
[
pil
]
;
s
bus_writel
(
cpu_pil_to_imask
[
pil
],
&
sun4m_irq_global
->
mask_set
)
;
}
static
void
sun4m_enable_pil_irq
(
unsigned
int
pil
)
{
s
un4m_interrupts
->
clear
=
cpu_pil_to_imask
[
pil
]
;
s
bus_writel
(
cpu_pil_to_imask
[
pil
],
&
sun4m_irq_global
->
mask_clear
)
;
}
#ifdef CONFIG_SMP
static
void
sun4m_send_ipi
(
int
cpu
,
int
level
)
{
unsigned
long
mask
;
mask
=
sun4m_get_irqmask
(
level
);
sun4m_interrupts
->
cpu_intregs
[
cpu
].
set
=
mask
;
unsigned
long
mask
=
sun4m_get_irqmask
(
level
);
sbus_writel
(
mask
,
&
sun4m_irq_percpu
[
cpu
]
->
set
);
}
static
void
sun4m_clear_ipi
(
int
cpu
,
int
level
)
{
unsigned
long
mask
;
mask
=
sun4m_get_irqmask
(
level
);
sun4m_interrupts
->
cpu_intregs
[
cpu
].
clear
=
mask
;
unsigned
long
mask
=
sun4m_get_irqmask
(
level
);
sbus_writel
(
mask
,
&
sun4m_irq_percpu
[
cpu
]
->
clear
);
}
static
void
sun4m_set_udt
(
int
cpu
)
{
s
un4m_interrupts
->
undirected_target
=
cpu
;
s
bus_writel
(
cpu
,
&
sun4m_irq_global
->
interrupt_target
)
;
}
#endif
...
...
@@ -347,7 +315,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
for
(
i
=
0
;
i
<
num_cpu_timers
;
i
++
)
sbus_writel
(
0
,
&
timers_percpu
[
i
]
->
l14_limit
);
if
(
num_cpu_timers
==
4
)
sbus_writel
(
SUN4M_INT_E14
,
&
sun4m_i
nterrupts
->
set
);
sbus_writel
(
SUN4M_INT_E14
,
&
sun4m_i
rq_global
->
mask_
set
);
#ifdef CONFIG_SMP
{
...
...
@@ -372,62 +340,38 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
void
__init
sun4m_init_IRQ
(
void
)
{
int
ie_node
,
i
;
struct
linux_prom_registers
int_regs
[
PROMREG_MAX
];
int
num_regs
;
struct
resource
r
;
int
mid
;
local_irq_disable
();
if
((
ie_node
=
prom_searchsiblings
(
prom_getchild
(
prom_root_node
),
"obio"
))
==
0
||
(
ie_node
=
prom_getchild
(
ie_node
))
==
0
||
(
ie_node
=
prom_searchsiblings
(
ie_node
,
"interrupt"
))
==
0
)
{
prom_printf
(
"Cannot find /obio/interrupt node
\n
"
);
prom_halt
();
struct
device_node
*
dp
=
of_find_node_by_name
(
NULL
,
"interrupt"
);
int
len
,
i
,
mid
,
num_cpu_iregs
;
const
u32
*
addr
;
if
(
!
dp
)
{
printk
(
KERN_ERR
"sun4m_init_IRQ: No 'interrupt' node.
\n
"
);
return
;
}
num_regs
=
prom_getproperty
(
ie_node
,
"reg"
,
(
char
*
)
int_regs
,
sizeof
(
int_regs
));
num_regs
=
(
num_regs
/
sizeof
(
struct
linux_prom_registers
));
/* Apply the obio ranges to these registers. */
prom_apply_obio_ranges
(
int_regs
,
num_regs
);
int_regs
[
4
].
phys_addr
=
int_regs
[
num_regs
-
1
].
phys_addr
;
int_regs
[
4
].
reg_size
=
int_regs
[
num_regs
-
1
].
reg_size
;
int_regs
[
4
].
which_io
=
int_regs
[
num_regs
-
1
].
which_io
;
for
(
ie_node
=
1
;
ie_node
<
4
;
ie_node
++
)
{
int_regs
[
ie_node
].
phys_addr
=
int_regs
[
ie_node
-
1
].
phys_addr
+
PAGE_SIZE
;
int_regs
[
ie_node
].
reg_size
=
int_regs
[
ie_node
-
1
].
reg_size
;
int_regs
[
ie_node
].
which_io
=
int_regs
[
ie_node
-
1
].
which_io
;
addr
=
of_get_property
(
dp
,
"address"
,
&
len
);
if
(
!
addr
)
{
printk
(
KERN_ERR
"sun4m_init_IRQ: No 'address' prop.
\n
"
);
return
;
}
memset
((
char
*
)
&
r
,
0
,
sizeof
(
struct
resource
));
/* Map the interrupt registers for all possible cpus. */
r
.
flags
=
int_regs
[
0
].
which_io
;
r
.
start
=
int_regs
[
0
].
phys_addr
;
sun4m_interrupts
=
(
struct
sun4m_intregs
*
)
of_ioremap
(
&
r
,
0
,
PAGE_SIZE
*
SUN4M_NCPUS
,
"interrupts_percpu"
);
num_cpu_iregs
=
(
len
/
sizeof
(
u32
))
-
1
;
for
(
i
=
0
;
i
<
num_cpu_iregs
;
i
++
)
{
sun4m_irq_percpu
[
i
]
=
(
void
__iomem
*
)
(
unsigned
long
)
addr
[
i
];
}
sun4m_irq_global
=
(
void
__iomem
*
)
(
unsigned
long
)
addr
[
num_cpu_iregs
];
/* Map the system interrupt control registers. */
r
.
flags
=
int_regs
[
4
].
which_io
;
r
.
start
=
int_regs
[
4
].
phys_addr
;
of_ioremap
(
&
r
,
0
,
int_regs
[
4
].
reg_size
,
"interrupts_system"
);
local_irq_disable
();
s
un4m_interrupts
->
set
=
~
SUN4M_INT_MASKALL
;
s
bus_writel
(
~
SUN4M_INT_MASKALL
,
&
sun4m_irq_global
->
mask_set
)
;
for
(
i
=
0
;
!
cpu_find_by_instance
(
i
,
NULL
,
&
mid
);
i
++
)
sun4m_interrupts
->
cpu_intregs
[
mid
].
clear
=
~
0x17fff
;
if
(
!
cpu_find_by_instance
(
1
,
NULL
,
NULL
))
{
/* system wide interrupts go to cpu 0, this should always
* be safe because it is guaranteed to be fitted or OBP doesn't
* come up
*
* Not sure, but writing here on SLAVIO systems may puke
* so I don't do it unless there is more than 1 cpu.
*/
irq_rcvreg
=
(
unsigned
long
*
)
&
sun4m_interrupts
->
undirected_target
;
sun4m_interrupts
->
undirected_target
=
0
;
sbus_writel
(
~
0x17fff
,
&
sun4m_irq_percpu
[
mid
]
->
clear
);
if
(
num_cpu_iregs
==
4
)
{
irq_rcvreg
=
(
unsigned
long
*
)
&
sun4m_irq_global
->
interrupt_target
;
sbus_writel
(
0
,
&
sun4m_irq_global
->
interrupt_target
);
}
BTFIXUPSET_CALL
(
enable_irq
,
sun4m_enable_irq
,
BTFIXUPCALL_NORM
);
BTFIXUPSET_CALL
(
disable_irq
,
sun4m_disable_irq
,
BTFIXUPCALL_NORM
);
...
...
@@ -442,5 +386,6 @@ void __init sun4m_init_IRQ(void)
BTFIXUPSET_CALL
(
clear_cpu_int
,
sun4m_clear_ipi
,
BTFIXUPCALL_NORM
);
BTFIXUPSET_CALL
(
set_irq_udt
,
sun4m_set_udt
,
BTFIXUPCALL_NORM
);
#endif
/* Cannot enable interrupts until OBP ticker is disabled. */
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录