Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
f7867cff
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
f7867cff
编写于
3月 16, 2020
作者:
D
Daniel Lezcano
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'timers/drivers/timer-ti-dm' into timers/drivers/next
上级
05852445
02e6d546
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
119 addition
and
82 deletion
+119
-82
drivers/clocksource/timer-ti-dm.c
drivers/clocksource/timer-ti-dm.c
+109
-74
drivers/pwm/pwm-omap-dmtimer.c
drivers/pwm/pwm-omap-dmtimer.c
+5
-3
include/clocksource/timer-ti-dm.h
include/clocksource/timer-ti-dm.h
+2
-2
include/linux/platform_data/dmtimer-omap.h
include/linux/platform_data/dmtimer-omap.h
+3
-3
未找到文件。
drivers/clocksource/timer-ti-dm.c
浏览文件 @
f7867cff
// SPDX-License-Identifier: GPL-2.0+
/*
* linux/arch/arm/plat-omap/dmtimer.c
*
...
...
@@ -15,28 +16,11 @@
*
* Copyright (C) 2009 Texas Instruments
* Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/cpu_pm.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/device.h>
...
...
@@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
timer
->
context
.
tclr
);
}
static
void
omap_timer_save_context
(
struct
omap_dm_timer
*
timer
)
{
timer
->
context
.
tclr
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
timer
->
context
.
twer
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_WAKEUP_EN_REG
);
timer
->
context
.
tldr
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_LOAD_REG
);
timer
->
context
.
tmar
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_MATCH_REG
);
timer
->
context
.
tier
=
readl_relaxed
(
timer
->
irq_ena
);
timer
->
context
.
tsicr
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_IF_CTRL_REG
);
}
static
int
omap_timer_context_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
cmd
,
void
*
v
)
{
struct
omap_dm_timer
*
timer
;
timer
=
container_of
(
nb
,
struct
omap_dm_timer
,
nb
);
switch
(
cmd
)
{
case
CPU_CLUSTER_PM_ENTER
:
if
((
timer
->
capability
&
OMAP_TIMER_ALWON
)
||
!
atomic_read
(
&
timer
->
enabled
))
break
;
omap_timer_save_context
(
timer
);
break
;
case
CPU_CLUSTER_PM_ENTER_FAILED
:
case
CPU_CLUSTER_PM_EXIT
:
if
((
timer
->
capability
&
OMAP_TIMER_ALWON
)
||
!
atomic_read
(
&
timer
->
enabled
))
break
;
omap_timer_restore_context
(
timer
);
break
;
}
return
NOTIFY_OK
;
}
static
int
omap_dm_timer_reset
(
struct
omap_dm_timer
*
timer
)
{
u32
l
,
timeout
=
100000
;
...
...
@@ -196,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
static
void
omap_dm_timer_enable
(
struct
omap_dm_timer
*
timer
)
{
int
c
;
pm_runtime_get_sync
(
&
timer
->
pdev
->
dev
);
if
(
!
(
timer
->
capability
&
OMAP_TIMER_ALWON
))
{
if
(
timer
->
get_context_loss_count
)
{
c
=
timer
->
get_context_loss_count
(
&
timer
->
pdev
->
dev
);
if
(
c
!=
timer
->
ctx_loss_count
)
{
omap_timer_restore_context
(
timer
);
timer
->
ctx_loss_count
=
c
;
}
}
else
{
omap_timer_restore_context
(
timer
);
}
}
}
static
void
omap_dm_timer_disable
(
struct
omap_dm_timer
*
timer
)
...
...
@@ -477,7 +488,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
int
omap_dm_timer_trigger
(
struct
omap_dm_timer
*
timer
)
{
if
(
unlikely
(
!
timer
||
pm_runtime_suspended
(
&
timer
->
pdev
->
dev
)))
{
if
(
unlikely
(
!
timer
||
!
atomic_read
(
&
timer
->
enabled
)))
{
pr_err
(
"%s: timer not available or enabled.
\n
"
,
__func__
);
return
-
EINVAL
;
}
...
...
@@ -501,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
}
/* Save the context */
timer
->
context
.
tclr
=
l
;
return
0
;
}
...
...
@@ -518,37 +527,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
__omap_dm_timer_stop
(
timer
,
timer
->
posted
,
rate
);
/*
* Since the register values are computed and written within
* __omap_dm_timer_stop, we need to use read to retrieve the
* context.
*/
timer
->
context
.
tclr
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
omap_dm_timer_disable
(
timer
);
return
0
;
}
static
int
omap_dm_timer_set_load
(
struct
omap_dm_timer
*
timer
,
int
autoreload
,
static
int
omap_dm_timer_set_load
(
struct
omap_dm_timer
*
timer
,
unsigned
int
load
)
{
u32
l
;
if
(
unlikely
(
!
timer
))
return
-
EINVAL
;
omap_dm_timer_enable
(
timer
);
l
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
if
(
autoreload
)
l
|=
OMAP_TIMER_CTRL_AR
;
else
l
&=
~
OMAP_TIMER_CTRL_AR
;
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_LOAD_REG
,
load
);
/* Save the context */
timer
->
context
.
tclr
=
l
;
timer
->
context
.
tldr
=
load
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
...
...
@@ -570,15 +561,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_MATCH_REG
,
match
);
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
/* Save the context */
timer
->
context
.
tclr
=
l
;
timer
->
context
.
tmar
=
match
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
static
int
omap_dm_timer_set_pwm
(
struct
omap_dm_timer
*
timer
,
int
def_on
,
int
toggle
,
int
trigger
)
int
toggle
,
int
trigger
,
int
autoreload
)
{
u32
l
;
...
...
@@ -588,20 +576,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
omap_dm_timer_enable
(
timer
);
l
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
l
&=
~
(
OMAP_TIMER_CTRL_GPOCFG
|
OMAP_TIMER_CTRL_SCPWM
|
OMAP_TIMER_CTRL_PT
|
(
0x03
<<
10
));
OMAP_TIMER_CTRL_PT
|
(
0x03
<<
10
)
|
OMAP_TIMER_CTRL_AR
);
if
(
def_on
)
l
|=
OMAP_TIMER_CTRL_SCPWM
;
if
(
toggle
)
l
|=
OMAP_TIMER_CTRL_PT
;
l
|=
trigger
<<
10
;
if
(
autoreload
)
l
|=
OMAP_TIMER_CTRL_AR
;
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
/* Save the context */
timer
->
context
.
tclr
=
l
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
static
int
omap_dm_timer_get_pwm_status
(
struct
omap_dm_timer
*
timer
)
{
u32
l
;
if
(
unlikely
(
!
timer
))
return
-
EINVAL
;
omap_dm_timer_enable
(
timer
);
l
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
omap_dm_timer_disable
(
timer
);
return
l
;
}
static
int
omap_dm_timer_set_prescaler
(
struct
omap_dm_timer
*
timer
,
int
prescaler
)
{
...
...
@@ -619,8 +621,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
}
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
/* Save the context */
timer
->
context
.
tclr
=
l
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
...
...
@@ -634,9 +634,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
omap_dm_timer_enable
(
timer
);
__omap_dm_timer_int_enable
(
timer
,
value
);
/* Save the context */
timer
->
context
.
tier
=
value
;
timer
->
context
.
twer
=
value
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
...
...
@@ -664,9 +661,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
l
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_WAKEUP_EN_REG
)
&
~
mask
;
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_WAKEUP_EN_REG
,
l
);
/* Save the context */
timer
->
context
.
tier
&=
~
mask
;
timer
->
context
.
twer
&=
~
mask
;
omap_dm_timer_disable
(
timer
);
return
0
;
}
...
...
@@ -675,7 +669,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
unsigned
int
l
;
if
(
unlikely
(
!
timer
||
pm_runtime_suspended
(
&
timer
->
pdev
->
dev
)))
{
if
(
unlikely
(
!
timer
||
!
atomic_read
(
&
timer
->
enabled
)))
{
pr_err
(
"%s: timer not available or enabled.
\n
"
,
__func__
);
return
0
;
}
...
...
@@ -687,7 +681,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
static
int
omap_dm_timer_write_status
(
struct
omap_dm_timer
*
timer
,
unsigned
int
value
)
{
if
(
unlikely
(
!
timer
||
pm_runtime_suspended
(
&
timer
->
pdev
->
dev
)))
if
(
unlikely
(
!
timer
||
!
atomic_read
(
&
timer
->
enabled
)))
return
-
EINVAL
;
__omap_dm_timer_write_status
(
timer
,
value
);
...
...
@@ -697,7 +691,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int
static
unsigned
int
omap_dm_timer_read_counter
(
struct
omap_dm_timer
*
timer
)
{
if
(
unlikely
(
!
timer
||
pm_runtime_suspended
(
&
timer
->
pdev
->
dev
)))
{
if
(
unlikely
(
!
timer
||
!
atomic_read
(
&
timer
->
enabled
)))
{
pr_err
(
"%s: timer not iavailable or enabled.
\n
"
,
__func__
);
return
0
;
}
...
...
@@ -707,7 +701,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
static
int
omap_dm_timer_write_counter
(
struct
omap_dm_timer
*
timer
,
unsigned
int
value
)
{
if
(
unlikely
(
!
timer
||
pm_runtime_suspended
(
&
timer
->
pdev
->
dev
)))
{
if
(
unlikely
(
!
timer
||
!
atomic_read
(
&
timer
->
enabled
)))
{
pr_err
(
"%s: timer not available or enabled.
\n
"
,
__func__
);
return
-
EINVAL
;
}
...
...
@@ -735,6 +729,37 @@ int omap_dm_timers_active(void)
return
0
;
}
static
int
__maybe_unused
omap_dm_timer_runtime_suspend
(
struct
device
*
dev
)
{
struct
omap_dm_timer
*
timer
=
dev_get_drvdata
(
dev
);
atomic_set
(
&
timer
->
enabled
,
0
);
if
(
timer
->
capability
&
OMAP_TIMER_ALWON
||
!
timer
->
func_base
)
return
0
;
omap_timer_save_context
(
timer
);
return
0
;
}
static
int
__maybe_unused
omap_dm_timer_runtime_resume
(
struct
device
*
dev
)
{
struct
omap_dm_timer
*
timer
=
dev_get_drvdata
(
dev
);
if
(
!
(
timer
->
capability
&
OMAP_TIMER_ALWON
)
&&
timer
->
func_base
)
omap_timer_restore_context
(
timer
);
atomic_set
(
&
timer
->
enabled
,
1
);
return
0
;
}
static
const
struct
dev_pm_ops
omap_dm_timer_pm_ops
=
{
SET_RUNTIME_PM_OPS
(
omap_dm_timer_runtime_suspend
,
omap_dm_timer_runtime_resume
,
NULL
)
};
static
const
struct
of_device_id
omap_timer_match
[];
/**
...
...
@@ -776,6 +801,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
if
(
IS_ERR
(
timer
->
io_base
))
return
PTR_ERR
(
timer
->
io_base
);
platform_set_drvdata
(
pdev
,
timer
);
if
(
dev
->
of_node
)
{
if
(
of_find_property
(
dev
->
of_node
,
"ti,timer-alwon"
,
NULL
))
timer
->
capability
|=
OMAP_TIMER_ALWON
;
...
...
@@ -789,7 +816,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
timer
->
id
=
pdev
->
id
;
timer
->
capability
=
pdata
->
timer_capability
;
timer
->
reserved
=
omap_dm_timer_reserved_systimer
(
timer
->
id
);
timer
->
get_context_loss_count
=
pdata
->
get_context_loss_count
;
}
if
(
!
(
timer
->
capability
&
OMAP_TIMER_ALWON
))
{
timer
->
nb
.
notifier_call
=
omap_timer_context_notifier
;
cpu_pm_register_notifier
(
&
timer
->
nb
);
}
if
(
pdata
)
...
...
@@ -843,6 +874,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
list_for_each_entry
(
timer
,
&
omap_timer_list
,
node
)
if
(
!
strcmp
(
dev_name
(
&
timer
->
pdev
->
dev
),
dev_name
(
&
pdev
->
dev
)))
{
if
(
!
(
timer
->
capability
&
OMAP_TIMER_ALWON
))
cpu_pm_unregister_notifier
(
&
timer
->
nb
);
list_del
(
&
timer
->
node
);
ret
=
0
;
break
;
...
...
@@ -871,6 +904,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
.
set_load
=
omap_dm_timer_set_load
,
.
set_match
=
omap_dm_timer_set_match
,
.
set_pwm
=
omap_dm_timer_set_pwm
,
.
get_pwm_status
=
omap_dm_timer_get_pwm_status
,
.
set_prescaler
=
omap_dm_timer_set_prescaler
,
.
read_counter
=
omap_dm_timer_read_counter
,
.
write_counter
=
omap_dm_timer_write_counter
,
...
...
@@ -921,6 +955,7 @@ static struct platform_driver omap_dm_timer_driver = {
.
driver
=
{
.
name
=
"omap_timer"
,
.
of_match_table
=
of_match_ptr
(
omap_timer_match
),
.
pm
=
&
omap_dm_timer_pm_ops
,
},
};
...
...
drivers/pwm/pwm-omap-dmtimer.c
浏览文件 @
f7867cff
...
...
@@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
if
(
timer_active
)
omap
->
pdata
->
stop
(
omap
->
dm_timer
);
omap
->
pdata
->
set_load
(
omap
->
dm_timer
,
true
,
load_value
);
omap
->
pdata
->
set_load
(
omap
->
dm_timer
,
load_value
);
omap
->
pdata
->
set_match
(
omap
->
dm_timer
,
true
,
match_value
);
dev_dbg
(
chip
->
dev
,
"load value: %#08x (%d), match value: %#08x (%d)
\n
"
,
...
...
@@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
omap
->
pdata
->
set_pwm
(
omap
->
dm_timer
,
pwm_get_polarity
(
pwm
)
==
PWM_POLARITY_INVERSED
,
true
,
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE
);
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE
,
true
);
/* If config was called while timer was running it must be reenabled. */
if
(
timer_active
)
...
...
@@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
omap
->
pdata
->
set_pwm
(
omap
->
dm_timer
,
polarity
==
PWM_POLARITY_INVERSED
,
true
,
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE
);
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE
,
true
);
mutex_unlock
(
&
omap
->
mutex
);
return
0
;
...
...
include/clocksource/timer-ti-dm.h
浏览文件 @
f7867cff
...
...
@@ -105,17 +105,17 @@ struct omap_dm_timer {
void
__iomem
*
pend
;
/* write pending */
void
__iomem
*
func_base
;
/* function register base */
atomic_t
enabled
;
unsigned
long
rate
;
unsigned
reserved
:
1
;
unsigned
posted
:
1
;
struct
timer_regs
context
;
int
(
*
get_context_loss_count
)(
struct
device
*
);
int
ctx_loss_count
;
int
revision
;
u32
capability
;
u32
errata
;
struct
platform_device
*
pdev
;
struct
list_head
node
;
struct
notifier_block
nb
;
};
int
omap_dm_timer_reserve_systimer
(
int
id
);
...
...
include/linux/platform_data/dmtimer-omap.h
浏览文件 @
f7867cff
...
...
@@ -30,12 +30,12 @@ struct omap_dm_timer_ops {
int
(
*
stop
)(
struct
omap_dm_timer
*
timer
);
int
(
*
set_source
)(
struct
omap_dm_timer
*
timer
,
int
source
);
int
(
*
set_load
)(
struct
omap_dm_timer
*
timer
,
int
autoreload
,
unsigned
int
value
);
int
(
*
set_load
)(
struct
omap_dm_timer
*
timer
,
unsigned
int
value
);
int
(
*
set_match
)(
struct
omap_dm_timer
*
timer
,
int
enable
,
unsigned
int
match
);
int
(
*
set_pwm
)(
struct
omap_dm_timer
*
timer
,
int
def_on
,
int
toggle
,
int
trigger
);
int
toggle
,
int
trigger
,
int
autoreload
);
int
(
*
get_pwm_status
)(
struct
omap_dm_timer
*
timer
);
int
(
*
set_prescaler
)(
struct
omap_dm_timer
*
timer
,
int
prescaler
);
unsigned
int
(
*
read_counter
)(
struct
omap_dm_timer
*
timer
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录