Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gsplhtlxg
clone-Linux
提交
e3887714
C
clone-Linux
项目概览
gsplhtlxg
/
clone-Linux
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
clone-Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e3887714
编写于
1月 14, 2010
作者:
R
Russell King
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ARM: Realview/Versatile: separate out common SP804 timer code
Signed-off-by:
N
Russell King
<
rmk+kernel@arm.linux.org.uk
>
上级
f4b8b319
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
182 addition
and
268 deletion
+182
-268
arch/arm/Kconfig
arch/arm/Kconfig
+5
-0
arch/arm/mach-realview/core.c
arch/arm/mach-realview/core.c
+3
-136
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/core.c
+3
-132
arch/arm/plat-versatile/Makefile
arch/arm/plat-versatile/Makefile
+1
-0
arch/arm/plat-versatile/include/plat/timer-sp.h
arch/arm/plat-versatile/include/plat/timer-sp.h
+2
-0
arch/arm/plat-versatile/timer-sp.c
arch/arm/plat-versatile/timer-sp.c
+168
-0
未找到文件。
arch/arm/Kconfig
浏览文件 @
e3887714
...
...
@@ -257,6 +257,7 @@ config ARCH_REALVIEW
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
select PLAT_VERSATILE
select ARM_TIMER_SP804
help
This enables support for ARM Ltd RealView boards.
...
...
@@ -271,6 +272,7 @@ config ARCH_VERSATILE
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
select PLAT_VERSATILE
select ARM_TIMER_SP804
help
This enables support for ARM Ltd Versatile board.
...
...
@@ -944,6 +946,9 @@ config PLAT_PXA
config PLAT_VERSATILE
bool
config ARM_TIMER_SP804
bool
source arch/arm/mm/Kconfig
config IWMMXT
...
...
arch/arm/mach-realview/core.c
浏览文件 @
e3887714
...
...
@@ -25,8 +25,6 @@
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
#include <linux/smsc911x.h>
#include <linux/ata_platform.h>
...
...
@@ -51,6 +49,7 @@
#include <mach/clkdev.h>
#include <mach/platform.h>
#include <mach/irqs.h>
#include <plat/timer-sp.h>
#include "core.h"
...
...
@@ -645,133 +644,6 @@ void __iomem *timer1_va_base;
void
__iomem
*
timer2_va_base
;
void
__iomem
*
timer3_va_base
;
/*
* How long is the timer interval?
*/
#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
#if TIMER_INTERVAL >= 0x100000
#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
#elif TIMER_INTERVAL >= 0x10000
#define TIMER_RELOAD (TIMER_INTERVAL >> 4)
/* Divide by 16 */
#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
#else
#define TIMER_RELOAD (TIMER_INTERVAL)
#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
#endif
static
void
timer_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
clk
)
{
unsigned
long
ctrl
;
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
writel
(
TIMER_RELOAD
,
timer0_va_base
+
TIMER_LOAD
);
ctrl
=
TIMER_CTRL_PERIODIC
;
ctrl
|=
TIMER_CTRL_32BIT
|
TIMER_CTRL_IE
|
TIMER_CTRL_ENABLE
;
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* period set, and timer enabled in 'next_event' hook */
ctrl
=
TIMER_CTRL_ONESHOT
;
ctrl
|=
TIMER_CTRL_32BIT
|
TIMER_CTRL_IE
;
break
;
case
CLOCK_EVT_MODE_UNUSED
:
case
CLOCK_EVT_MODE_SHUTDOWN
:
default:
ctrl
=
0
;
}
writel
(
ctrl
,
timer0_va_base
+
TIMER_CTRL
);
}
static
int
timer_set_next_event
(
unsigned
long
evt
,
struct
clock_event_device
*
unused
)
{
unsigned
long
ctrl
=
readl
(
timer0_va_base
+
TIMER_CTRL
);
writel
(
evt
,
timer0_va_base
+
TIMER_LOAD
);
writel
(
ctrl
|
TIMER_CTRL_ENABLE
,
timer0_va_base
+
TIMER_CTRL
);
return
0
;
}
static
struct
clock_event_device
timer0_clockevent
=
{
.
name
=
"timer0"
,
.
shift
=
32
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
,
.
set_mode
=
timer_set_mode
,
.
set_next_event
=
timer_set_next_event
,
.
rating
=
300
,
.
cpumask
=
cpu_all_mask
,
};
static
void
__init
realview_clockevents_init
(
unsigned
int
timer_irq
)
{
timer0_clockevent
.
irq
=
timer_irq
;
timer0_clockevent
.
mult
=
div_sc
(
1000000
,
NSEC_PER_SEC
,
timer0_clockevent
.
shift
);
timer0_clockevent
.
max_delta_ns
=
clockevent_delta2ns
(
0xffffffff
,
&
timer0_clockevent
);
timer0_clockevent
.
min_delta_ns
=
clockevent_delta2ns
(
0xf
,
&
timer0_clockevent
);
clockevents_register_device
(
&
timer0_clockevent
);
}
/*
* IRQ handler for the timer
*/
static
irqreturn_t
realview_timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
evt
=
&
timer0_clockevent
;
/* clear the interrupt */
writel
(
1
,
timer0_va_base
+
TIMER_INTCLR
);
evt
->
event_handler
(
evt
);
return
IRQ_HANDLED
;
}
static
struct
irqaction
realview_timer_irq
=
{
.
name
=
"RealView Timer Tick"
,
.
flags
=
IRQF_DISABLED
|
IRQF_TIMER
|
IRQF_IRQPOLL
,
.
handler
=
realview_timer_interrupt
,
};
static
cycle_t
realview_get_cycles
(
struct
clocksource
*
cs
)
{
return
~
readl
(
timer3_va_base
+
TIMER_VALUE
);
}
static
struct
clocksource
clocksource_realview
=
{
.
name
=
"timer3"
,
.
rating
=
200
,
.
read
=
realview_get_cycles
,
.
mask
=
CLOCKSOURCE_MASK
(
32
),
.
shift
=
20
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
static
void
__init
realview_clocksource_init
(
void
)
{
/* setup timer 0 as free-running clocksource */
writel
(
0
,
timer3_va_base
+
TIMER_CTRL
);
writel
(
0xffffffff
,
timer3_va_base
+
TIMER_LOAD
);
writel
(
0xffffffff
,
timer3_va_base
+
TIMER_VALUE
);
writel
(
TIMER_CTRL_32BIT
|
TIMER_CTRL_ENABLE
|
TIMER_CTRL_PERIODIC
,
timer3_va_base
+
TIMER_CTRL
);
clocksource_realview
.
mult
=
clocksource_khz2mult
(
1000
,
clocksource_realview
.
shift
);
clocksource_register
(
&
clocksource_realview
);
}
/*
* Set up the clock source and clock events devices
*/
...
...
@@ -799,13 +671,8 @@ void __init realview_timer_init(unsigned int timer_irq)
writel
(
0
,
timer2_va_base
+
TIMER_CTRL
);
writel
(
0
,
timer3_va_base
+
TIMER_CTRL
);
/*
* Make irqs happen for the system timer
*/
setup_irq
(
timer_irq
,
&
realview_timer_irq
);
realview_clocksource_init
();
realview_clockevents_init
(
timer_irq
);
sp804_clocksource_init
(
timer3_va_base
);
sp804_clockevents_init
(
timer0_va_base
,
timer_irq
);
}
/*
...
...
arch/arm/mach-versatile/core.c
浏览文件 @
e3887714
...
...
@@ -28,8 +28,6 @@
#include <linux/amba/clcd.h>
#include <linux/amba/pl061.h>
#include <linux/amba/mmci.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/cnt32_to_63.h>
#include <linux/io.h>
...
...
@@ -50,6 +48,7 @@
#include <mach/clkdev.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include <plat/timer-sp.h>
#include "core.h"
...
...
@@ -877,120 +876,6 @@ void __init versatile_init(void)
#define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20)
#define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE)
#define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20)
#define VA_IC_BASE __io_address(VERSATILE_VIC_BASE)
/*
* How long is the timer interval?
*/
#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
#if TIMER_INTERVAL >= 0x100000
#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
#elif TIMER_INTERVAL >= 0x10000
#define TIMER_RELOAD (TIMER_INTERVAL >> 4)
/* Divide by 16 */
#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
#else
#define TIMER_RELOAD (TIMER_INTERVAL)
#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
#endif
static
void
timer_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
clk
)
{
unsigned
long
ctrl
;
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
writel
(
TIMER_RELOAD
,
TIMER0_VA_BASE
+
TIMER_LOAD
);
ctrl
=
TIMER_CTRL_PERIODIC
;
ctrl
|=
TIMER_CTRL_32BIT
|
TIMER_CTRL_IE
|
TIMER_CTRL_ENABLE
;
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* period set, and timer enabled in 'next_event' hook */
ctrl
=
TIMER_CTRL_ONESHOT
;
ctrl
|=
TIMER_CTRL_32BIT
|
TIMER_CTRL_IE
;
break
;
case
CLOCK_EVT_MODE_UNUSED
:
case
CLOCK_EVT_MODE_SHUTDOWN
:
default:
ctrl
=
0
;
}
writel
(
ctrl
,
TIMER0_VA_BASE
+
TIMER_CTRL
);
}
static
int
timer_set_next_event
(
unsigned
long
evt
,
struct
clock_event_device
*
unused
)
{
unsigned
long
ctrl
=
readl
(
TIMER0_VA_BASE
+
TIMER_CTRL
);
writel
(
evt
,
TIMER0_VA_BASE
+
TIMER_LOAD
);
writel
(
ctrl
|
TIMER_CTRL_ENABLE
,
TIMER0_VA_BASE
+
TIMER_CTRL
);
return
0
;
}
static
struct
clock_event_device
timer0_clockevent
=
{
.
name
=
"timer0"
,
.
shift
=
32
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
,
.
set_mode
=
timer_set_mode
,
.
set_next_event
=
timer_set_next_event
,
};
/*
* IRQ handler for the timer
*/
static
irqreturn_t
versatile_timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
evt
=
&
timer0_clockevent
;
writel
(
1
,
TIMER0_VA_BASE
+
TIMER_INTCLR
);
evt
->
event_handler
(
evt
);
return
IRQ_HANDLED
;
}
static
struct
irqaction
versatile_timer_irq
=
{
.
name
=
"Versatile Timer Tick"
,
.
flags
=
IRQF_DISABLED
|
IRQF_TIMER
|
IRQF_IRQPOLL
,
.
handler
=
versatile_timer_interrupt
,
};
static
cycle_t
versatile_get_cycles
(
struct
clocksource
*
cs
)
{
return
~
readl
(
TIMER3_VA_BASE
+
TIMER_VALUE
);
}
static
struct
clocksource
clocksource_versatile
=
{
.
name
=
"timer3"
,
.
rating
=
200
,
.
read
=
versatile_get_cycles
,
.
mask
=
CLOCKSOURCE_MASK
(
32
),
.
shift
=
20
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
static
int
__init
versatile_clocksource_init
(
void
)
{
/* setup timer3 as free-running clocksource */
writel
(
0
,
TIMER3_VA_BASE
+
TIMER_CTRL
);
writel
(
0xffffffff
,
TIMER3_VA_BASE
+
TIMER_LOAD
);
writel
(
0xffffffff
,
TIMER3_VA_BASE
+
TIMER_VALUE
);
writel
(
TIMER_CTRL_32BIT
|
TIMER_CTRL_ENABLE
|
TIMER_CTRL_PERIODIC
,
TIMER3_VA_BASE
+
TIMER_CTRL
);
clocksource_versatile
.
mult
=
clocksource_khz2mult
(
1000
,
clocksource_versatile
.
shift
);
clocksource_register
(
&
clocksource_versatile
);
return
0
;
}
/*
* Set up timer interrupt, and return the current time in seconds.
...
...
@@ -1019,22 +904,8 @@ static void __init versatile_timer_init(void)
writel
(
0
,
TIMER2_VA_BASE
+
TIMER_CTRL
);
writel
(
0
,
TIMER3_VA_BASE
+
TIMER_CTRL
);
/*
* Make irqs happen for the system timer
*/
setup_irq
(
IRQ_TIMERINT0_1
,
&
versatile_timer_irq
);
versatile_clocksource_init
();
timer0_clockevent
.
mult
=
div_sc
(
1000000
,
NSEC_PER_SEC
,
timer0_clockevent
.
shift
);
timer0_clockevent
.
max_delta_ns
=
clockevent_delta2ns
(
0xffffffff
,
&
timer0_clockevent
);
timer0_clockevent
.
min_delta_ns
=
clockevent_delta2ns
(
0xf
,
&
timer0_clockevent
);
timer0_clockevent
.
cpumask
=
cpumask_of
(
0
);
clockevents_register_device
(
&
timer0_clockevent
);
sp804_clocksource_init
(
TIMER3_VA_BASE
);
sp804_clockevents_init
(
TIMER0_VA_BASE
,
IRQ_TIMERINT0_1
);
}
struct
sys_timer
versatile_timer
=
{
...
...
arch/arm/plat-versatile/Makefile
浏览文件 @
e3887714
obj-y
:=
clock.o
obj-$(CONFIG_ARM_TIMER_SP804)
+=
timer-sp.o
arch/arm/plat-versatile/include/plat/timer-sp.h
0 → 100644
浏览文件 @
e3887714
void
sp804_clocksource_init
(
void
__iomem
*
);
void
sp804_clockevents_init
(
void
__iomem
*
,
unsigned
int
);
arch/arm/plat-versatile/timer-sp.c
0 → 100644
浏览文件 @
e3887714
/*
* linux/arch/arm/plat-versatile/timer-sp.c
*
* Copyright (C) 1999 - 2003 ARM Limited
* Copyright (C) 2000 Deep Blue Solutions Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/hardware/arm_timer.h>
#include <mach/platform.h>
#include <plat/timer-sp.h>
/*
* How long is the timer interval?
*/
#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
#if TIMER_INTERVAL >= 0x100000
#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
#elif TIMER_INTERVAL >= 0x10000
#define TIMER_RELOAD (TIMER_INTERVAL >> 4)
/* Divide by 16 */
#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
#else
#define TIMER_RELOAD (TIMER_INTERVAL)
#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
#endif
static
void
__iomem
*
clksrc_base
;
static
cycle_t
sp804_read
(
struct
clocksource
*
cs
)
{
return
~
readl
(
clksrc_base
+
TIMER_VALUE
);
}
static
struct
clocksource
clocksource_sp804
=
{
.
name
=
"timer3"
,
.
rating
=
200
,
.
read
=
sp804_read
,
.
mask
=
CLOCKSOURCE_MASK
(
32
),
.
shift
=
20
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
void
__init
sp804_clocksource_init
(
void
__iomem
*
base
)
{
struct
clocksource
*
cs
=
&
clocksource_sp804
;
clksrc_base
=
base
;
/* setup timer 0 as free-running clocksource */
writel
(
0
,
clksrc_base
+
TIMER_CTRL
);
writel
(
0xffffffff
,
clksrc_base
+
TIMER_LOAD
);
writel
(
0xffffffff
,
clksrc_base
+
TIMER_VALUE
);
writel
(
TIMER_CTRL_32BIT
|
TIMER_CTRL_ENABLE
|
TIMER_CTRL_PERIODIC
,
clksrc_base
+
TIMER_CTRL
);
cs
->
mult
=
clocksource_khz2mult
(
1000
,
cs
->
shift
);
clocksource_register
(
cs
);
}
static
void
__iomem
*
clkevt_base
;
/*
* IRQ handler for the timer
*/
static
irqreturn_t
sp804_timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
evt
=
dev_id
;
/* clear the interrupt */
writel
(
1
,
clkevt_base
+
TIMER_INTCLR
);
evt
->
event_handler
(
evt
);
return
IRQ_HANDLED
;
}
static
void
sp804_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
)
{
unsigned
long
ctrl
=
TIMER_CTRL_32BIT
|
TIMER_CTRL_IE
;
writel
(
ctrl
,
clkevt_base
+
TIMER_CTRL
);
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
writel
(
TIMER_RELOAD
,
clkevt_base
+
TIMER_LOAD
);
ctrl
|=
TIMER_CTRL_PERIODIC
|
TIMER_CTRL_ENABLE
;
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* period set, and timer enabled in 'next_event' hook */
ctrl
|=
TIMER_CTRL_ONESHOT
;
break
;
case
CLOCK_EVT_MODE_UNUSED
:
case
CLOCK_EVT_MODE_SHUTDOWN
:
default:
break
;
}
writel
(
ctrl
,
clkevt_base
+
TIMER_CTRL
);
}
static
int
sp804_set_next_event
(
unsigned
long
next
,
struct
clock_event_device
*
evt
)
{
unsigned
long
ctrl
=
readl
(
clkevt_base
+
TIMER_CTRL
);
writel
(
next
,
clkevt_base
+
TIMER_LOAD
);
writel
(
ctrl
|
TIMER_CTRL_ENABLE
,
clkevt_base
+
TIMER_CTRL
);
return
0
;
}
static
struct
clock_event_device
sp804_clockevent
=
{
.
name
=
"timer0"
,
.
shift
=
32
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
,
.
set_mode
=
sp804_set_mode
,
.
set_next_event
=
sp804_set_next_event
,
.
rating
=
300
,
.
cpumask
=
cpu_all_mask
,
};
static
struct
irqaction
sp804_timer_irq
=
{
.
name
=
"timer"
,
.
flags
=
IRQF_DISABLED
|
IRQF_TIMER
|
IRQF_IRQPOLL
,
.
handler
=
sp804_timer_interrupt
,
.
dev_id
=
&
sp804_clockevent
,
};
void
__init
sp804_clockevents_init
(
void
__iomem
*
base
,
unsigned
int
timer_irq
)
{
struct
clock_event_device
*
evt
=
&
sp804_clockevent
;
clkevt_base
=
base
;
evt
->
irq
=
timer_irq
;
evt
->
mult
=
div_sc
(
1000000
,
NSEC_PER_SEC
,
evt
->
shift
);
evt
->
max_delta_ns
=
clockevent_delta2ns
(
0xffffffff
,
evt
);
evt
->
min_delta_ns
=
clockevent_delta2ns
(
0xf
,
evt
);
setup_irq
(
timer_irq
,
&
sp804_timer_irq
);
clockevents_register_device
(
evt
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录