Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
9b9ea220
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
9b9ea220
编写于
10月 11, 2007
作者:
R
Ralf Baechle
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[MIPS] Clockevent driver for BCM1250
Signed-off-by:
N
Ralf Baechle
<
ralf@linux-mips.org
>
上级
d865bea4
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
160 addition
and
21 deletion
+160
-21
arch/mips/sibyte/sb1250/time.c
arch/mips/sibyte/sb1250/time.c
+160
-21
未找到文件。
arch/mips/sibyte/sb1250/time.c
浏览文件 @
9b9ea220
...
...
@@ -25,6 +25,7 @@
* code to do general bookkeeping (e.g. update jiffies, run
* bottom halves, etc.)
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
...
...
@@ -71,16 +72,158 @@ void __init sb1250_hpt_setup(void)
}
}
/*
* The general purpose timer ticks at 1 Mhz independent if
* the rest of the system
*/
static
void
sibyte_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
timer_cfg
,
*
timer_init
;
timer_cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
timer_init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
timer_cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
timer_init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
timer_cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
timer_cfg
);
break
;
void
sb1250_time_init
(
void
)
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
evt
)
{
int
cpu
=
smp_processor_id
();
int
irq
=
K_INT_TIMER_0
+
cpu
;
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
timer_cfg
,
*
timer_init
;
/* Only have 4 general purpose timers, and we use last one as hpt */
if
(
cpu
>
2
)
{
BUG
();
timer_cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
timer_init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
__raw_writeq
(
0
,
timer_cfg
);
__raw_writeq
(
delta
,
timer_init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
timer_cfg
);
return
0
;
}
struct
clock_event_device
sibyte_hpt_clockevent
=
{
.
name
=
"sb1250-counter"
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
,
.
set_mode
=
sibyte_set_mode
,
.
set_next_event
=
sibyte_next_event
,
.
shift
=
32
,
.
irq
=
0
,
};
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
cd
=
&
sibyte_hpt_clockevent
;
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
struct
irqaction
sibyte_irqaction
=
{
.
handler
=
sibyte_counter_handler
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"timer"
,
};
/*
* The general purpose timer ticks at 1 Mhz independent if
* the rest of the system
*/
static
void
sibyte_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
timer_cfg
,
*
timer_init
;
timer_cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
timer_init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
timer_cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
timer_init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
timer_cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
timer_cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
evt
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
timer_cfg
,
*
timer_init
;
timer_cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
timer_init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
__raw_writeq
(
0
,
timer_cfg
);
__raw_writeq
(
delta
,
timer_init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
timer_cfg
);
return
0
;
}
struct
clock_event_device
sibyte_hpt_clockevent
=
{
.
name
=
"sb1250-counter"
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
,
.
set_mode
=
sibyte_set_mode
,
.
set_next_event
=
sibyte_next_event
,
.
shift
=
32
,
.
irq
=
0
,
};
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
cd
=
&
sibyte_hpt_clockevent
;
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
struct
irqaction
sibyte_irqaction
=
{
.
handler
=
sibyte_counter_handler
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"timer"
,
};
static
void
__init
sb1250_clockevent_init
(
void
)
{
struct
clock_event_device
*
cd
=
&
sibyte_hpt_clockevent
;
unsigned
int
cpu
=
smp_processor_id
();
int
irq
=
K_INT_TIMER_0
+
cpu
;
/* Only have 4 general purpose timers, and we use last one as hpt */
BUG_ON
(
cpu
>
2
);
sb1250_mask_irq
(
cpu
,
irq
);
...
...
@@ -88,24 +231,11 @@ void sb1250_time_init(void)
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_IMR_REGISTER
(
cpu
,
R_IMR_INTERRUPT_MAP_BASE
)
+
(
irq
<<
3
)));
/* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
/* Disable the timer and set up the count */
__raw_writeq
(
0
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
#ifdef CONFIG_SIMULATION
__raw_writeq
((
50000
/
HZ
)
-
1
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
)));
#else
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
)));
#endif
/* Set the timer running */
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
cd
->
cpumask
=
cpumask_of_cpu
(
0
);
sb1250_unmask_irq
(
cpu
,
irq
);
sb1250_steal_irq
(
irq
);
/*
* This interrupt is "special" in that it doesn't use the request_irq
* way to hook the irq line. The timer interrupt is initialized early
...
...
@@ -114,6 +244,15 @@ void sb1250_time_init(void)
* called directly from irq_handler.S when IP[4] is set during an
* interrupt
*/
setup_irq
(
irq
,
&
sibyte_irqaction
);
clockevents_register_device
(
cd
);
}
void
__init
plat_time_init
(
void
)
{
sb1250_clocksource_init
();
sb1250_clockevent_init
();
}
/*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录