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
9dc57643
Commit
9dc57643
authored
Nov 13, 2012
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fixes-timer' of github.com:jonhunter/linux into omap-for-v3.8/timer
parents
d308ba50
b1538832
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
188 additions
and
91 deletions
+188
-91
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+14
-1
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+20
-21
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+4
-0
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/timer.c
+52
-18
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/dmtimer.c
+46
-31
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/dmtimer.h
+52
-20
No files found.
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
View file @
9dc57643
...
...
@@ -58,8 +58,9 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
.
syss_offs
=
0x0014
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_CLOCKACTIVITY
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
SYSC_HAS_AUTOIDLE
|
SYSS_HAS_RESET_STATUS
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
clockact
=
CLOCKACT_TEST_ICLK
,
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
...
...
@@ -268,6 +269,7 @@ struct omap_hwmod omap2xxx_timer1_hwmod = {
},
.
dev_attr
=
&
capability_alwon_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer2 */
...
...
@@ -286,6 +288,7 @@ struct omap_hwmod omap2xxx_timer2_hwmod = {
},
},
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer3 */
...
...
@@ -304,6 +307,7 @@ struct omap_hwmod omap2xxx_timer3_hwmod = {
},
},
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer4 */
...
...
@@ -322,6 +326,7 @@ struct omap_hwmod omap2xxx_timer4_hwmod = {
},
},
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer5 */
...
...
@@ -341,6 +346,7 @@ struct omap_hwmod omap2xxx_timer5_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer6 */
...
...
@@ -360,6 +366,7 @@ struct omap_hwmod omap2xxx_timer6_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer7 */
...
...
@@ -379,6 +386,7 @@ struct omap_hwmod omap2xxx_timer7_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer8 */
...
...
@@ -398,6 +406,7 @@ struct omap_hwmod omap2xxx_timer8_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer9 */
...
...
@@ -417,6 +426,7 @@ struct omap_hwmod omap2xxx_timer9_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer10 */
...
...
@@ -436,6 +446,7 @@ struct omap_hwmod omap2xxx_timer10_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer11 */
...
...
@@ -455,6 +466,7 @@ struct omap_hwmod omap2xxx_timer11_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer12 */
...
...
@@ -474,6 +486,7 @@ struct omap_hwmod omap2xxx_timer12_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap2xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* wd_timer2 */
...
...
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
View file @
9dc57643
...
...
@@ -153,29 +153,16 @@ static struct omap_hwmod omap3xxx_debugss_hwmod = {
};
/* timer class */
static
struct
omap_hwmod_class_sysconfig
omap3xxx_timer_1ms_sysc
=
{
.
rev_offs
=
0x0000
,
.
sysc_offs
=
0x0010
,
.
syss_offs
=
0x0014
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_CLOCKACTIVITY
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_EMUFREE
|
SYSC_HAS_AUTOIDLE
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
static
struct
omap_hwmod_class
omap3xxx_timer_1ms_hwmod_class
=
{
.
name
=
"timer"
,
.
sysc
=
&
omap3xxx_timer_1ms_sysc
,
};
static
struct
omap_hwmod_class_sysconfig
omap3xxx_timer_sysc
=
{
.
rev_offs
=
0x0000
,
.
sysc_offs
=
0x0010
,
.
syss_offs
=
0x0014
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_CLOCKACTIVITY
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_EMUFREE
|
SYSC_HAS_AUTOIDLE
|
SYSS_HAS_RESET_STATUS
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
clockact
=
CLOCKACT_TEST_ICLK
,
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
...
...
@@ -224,7 +211,8 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
},
},
.
dev_attr
=
&
capability_alwon_dev_attr
,
.
class
=
&
omap3xxx_timer_1ms_hwmod_class
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer2 */
...
...
@@ -241,7 +229,8 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
.
idlest_idle_bit
=
OMAP3430_ST_GPT2_SHIFT
,
},
},
.
class
=
&
omap3xxx_timer_1ms_hwmod_class
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer3 */
...
...
@@ -259,6 +248,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
},
},
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer4 */
...
...
@@ -276,6 +266,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
},
},
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer5 */
...
...
@@ -294,6 +285,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer6 */
...
...
@@ -312,6 +304,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer7 */
...
...
@@ -330,6 +323,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
},
.
dev_attr
=
&
capability_dsp_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer8 */
...
...
@@ -348,6 +342,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
},
.
dev_attr
=
&
capability_dsp_pwm_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer9 */
...
...
@@ -366,6 +361,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer10 */
...
...
@@ -383,7 +379,8 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
},
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap3xxx_timer_1ms_hwmod_class
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer11 */
...
...
@@ -402,6 +399,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
},
.
dev_attr
=
&
capability_pwm_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/* timer12 */
...
...
@@ -425,6 +423,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
},
.
dev_attr
=
&
capability_secure_dev_attr
,
.
class
=
&
omap3xxx_timer_hwmod_class
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
};
/*
...
...
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
View file @
9dc57643
...
...
@@ -3067,6 +3067,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_SOFTRESET
|
SYSS_HAS_RESET_STATUS
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
clockact
=
CLOCKACT_TEST_ICLK
,
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
...
...
@@ -3120,6 +3121,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
.
name
=
"timer1"
,
.
class
=
&
omap44xx_timer_1ms_hwmod_class
,
.
clkdm_name
=
"l4_wkup_clkdm"
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
.
mpu_irqs
=
omap44xx_timer1_irqs
,
.
main_clk
=
"timer1_fck"
,
.
prcm
=
{
...
...
@@ -3142,6 +3144,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
.
name
=
"timer2"
,
.
class
=
&
omap44xx_timer_1ms_hwmod_class
,
.
clkdm_name
=
"l4_per_clkdm"
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
.
mpu_irqs
=
omap44xx_timer2_irqs
,
.
main_clk
=
"timer2_fck"
,
.
prcm
=
{
...
...
@@ -3316,6 +3319,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
.
name
=
"timer10"
,
.
class
=
&
omap44xx_timer_1ms_hwmod_class
,
.
clkdm_name
=
"l4_per_clkdm"
,
.
flags
=
HWMOD_SET_DEFAULT_CLOCKACT
,
.
mpu_irqs
=
omap44xx_timer10_irqs
,
.
main_clk
=
"timer10_fck"
,
.
prcm
=
{
...
...
arch/arm/mach-omap2/timer.c
View file @
9dc57643
...
...
@@ -108,7 +108,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
struct
clock_event_device
*
evt
)
{
__omap_dm_timer_load_start
(
&
clkev
,
OMAP_TIMER_CTRL_ST
,
0xffffffff
-
cycles
,
1
);
0xffffffff
-
cycles
,
OMAP_TIMER_POSTED
);
return
0
;
}
...
...
@@ -118,7 +118,7 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
{
u32
period
;
__omap_dm_timer_stop
(
&
clkev
,
1
,
clkev
.
rate
);
__omap_dm_timer_stop
(
&
clkev
,
OMAP_TIMER_POSTED
,
clkev
.
rate
);
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
...
...
@@ -126,10 +126,10 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
period
-=
1
;
/* Looks like we need to first set the load value separately */
__omap_dm_timer_write
(
&
clkev
,
OMAP_TIMER_LOAD_REG
,
0xffffffff
-
period
,
1
);
0xffffffff
-
period
,
OMAP_TIMER_POSTED
);
__omap_dm_timer_load_start
(
&
clkev
,
OMAP_TIMER_CTRL_AR
|
OMAP_TIMER_CTRL_ST
,
0xffffffff
-
period
,
1
);
0xffffffff
-
period
,
OMAP_TIMER_POSTED
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
break
;
...
...
@@ -222,10 +222,24 @@ void __init omap_dmtimer_init(void)
}
}
/**
* omap_dm_timer_get_errata - get errata flags for a timer
*
* Get the timer errata flags that are specific to the OMAP device being used.
*/
u32
__init
omap_dm_timer_get_errata
(
void
)
{
if
(
cpu_is_omap24xx
())
return
0
;
return
OMAP_TIMER_ERRATA_I103_I767
;
}
static
int
__init
omap_dm_timer_init_one
(
struct
omap_dm_timer
*
timer
,
int
gptimer_id
,
const
char
*
fck_source
,
const
char
*
property
)
const
char
*
property
,
int
posted
)
{
char
name
[
10
];
/* 10 = sizeof("gptXX_Xck0") */
const
char
*
oh_name
;
...
...
@@ -260,9 +274,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
oh_name
=
name
;
}
omap_hwmod_setup_one
(
oh_name
);
oh
=
omap_hwmod_lookup
(
oh_name
);
if
(
!
oh
)
return
-
ENODEV
;
...
...
@@ -292,8 +304,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
if
(
IS_ERR
(
timer
->
fclk
))
return
-
ENODEV
;
omap_hwmod_enable
(
oh
);
/* FIXME: Need to remove hard-coded test on timer ID */
if
(
gptimer_id
!=
12
)
{
struct
clk
*
src
;
...
...
@@ -302,19 +312,26 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
if
(
IS_ERR
(
src
))
{
res
=
-
EINVAL
;
}
else
{
res
=
__omap_dm_timer_set_source
(
timer
->
fclk
,
src
);
res
=
clk_set_parent
(
timer
->
fclk
,
src
);
if
(
IS_ERR_VALUE
(
res
))
pr_warn
(
"%s: %s cannot set source
\n
"
,
__func__
,
oh
->
name
);
clk_put
(
src
);
}
}
omap_hwmod_setup_one
(
oh_name
);
omap_hwmod_enable
(
oh
);
__omap_dm_timer_init_regs
(
timer
);
__omap_dm_timer_reset
(
timer
,
1
,
1
);
timer
->
posted
=
1
;
timer
->
rate
=
clk_get_rate
(
timer
->
fclk
);
if
(
posted
)
__omap_dm_timer_enable_posted
(
timer
);
/* Check that the intended posted configuration matches the actual */
if
(
posted
!=
timer
->
posted
)
return
-
EINVAL
;
timer
->
rate
=
clk_get_rate
(
timer
->
fclk
);
timer
->
reserved
=
1
;
return
res
;
...
...
@@ -326,7 +343,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
{
int
res
;
res
=
omap_dm_timer_init_one
(
&
clkev
,
gptimer_id
,
fck_source
,
property
);
clkev
.
errata
=
omap_dm_timer_get_errata
();
/*
* For clock-event timers we never read the timer counter and
* so we are not impacted by errata i103 and i767. Therefore,
* we can safely ignore this errata for clock-event timers.
*/
__omap_dm_timer_override_errata
(
&
clkev
,
OMAP_TIMER_ERRATA_I103_I767
);
res
=
omap_dm_timer_init_one
(
&
clkev
,
gptimer_id
,
fck_source
,
property
,
OMAP_TIMER_POSTED
);
BUG_ON
(
res
);
omap2_gp_timer_irq
.
dev_id
=
&
clkev
;
...
...
@@ -359,7 +386,8 @@ static bool use_gptimer_clksrc;
*/
static
cycle_t
clocksource_read_cycles
(
struct
clocksource
*
cs
)
{
return
(
cycle_t
)
__omap_dm_timer_read_counter
(
&
clksrc
,
1
);
return
(
cycle_t
)
__omap_dm_timer_read_counter
(
&
clksrc
,
OMAP_TIMER_NONPOSTED
);
}
static
struct
clocksource
clocksource_gpt
=
{
...
...
@@ -373,7 +401,8 @@ static struct clocksource clocksource_gpt = {
static
u32
notrace
dmtimer_read_sched_clock
(
void
)
{
if
(
clksrc
.
reserved
)
return
__omap_dm_timer_read_counter
(
&
clksrc
,
1
);
return
__omap_dm_timer_read_counter
(
&
clksrc
,
OMAP_TIMER_NONPOSTED
);
return
0
;
}
...
...
@@ -451,11 +480,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
{
int
res
;
res
=
omap_dm_timer_init_one
(
&
clksrc
,
gptimer_id
,
fck_source
,
NULL
);
clksrc
.
errata
=
omap_dm_timer_get_errata
();
res
=
omap_dm_timer_init_one
(
&
clksrc
,
gptimer_id
,
fck_source
,
NULL
,
OMAP_TIMER_NONPOSTED
);
BUG_ON
(
res
);
__omap_dm_timer_load_start
(
&
clksrc
,
OMAP_TIMER_CTRL_ST
|
OMAP_TIMER_CTRL_AR
,
0
,
1
);
OMAP_TIMER_CTRL_ST
|
OMAP_TIMER_CTRL_AR
,
0
,
OMAP_TIMER_NONPOSTED
);
setup_sched_clock
(
dmtimer_read_sched_clock
,
32
,
clksrc
.
rate
);
if
(
clocksource_register_hz
(
&
clocksource_gpt
,
clksrc
.
rate
))
...
...
@@ -693,6 +726,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
if
(
timer_dev_attr
)
pdata
->
timer_capability
=
timer_dev_attr
->
timer_capability
;
pdata
->
timer_errata
=
omap_dm_timer_get_errata
();
pdata
->
get_context_loss_count
=
omap_pm_get_dev_context_loss_count
;
pdev
=
omap_device_build
(
name
,
id
,
oh
,
pdata
,
sizeof
(
*
pdata
),
...
...
arch/arm/plat-omap/dmtimer.c
View file @
9dc57643
...
...
@@ -35,6 +35,7 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/device.h>
...
...
@@ -83,10 +84,6 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
static
void
omap_timer_restore_context
(
struct
omap_dm_timer
*
timer
)
{
if
(
timer
->
revision
==
1
)
__raw_writel
(
timer
->
context
.
tistat
,
timer
->
sys_stat
);
__raw_writel
(
timer
->
context
.
tisr
,
timer
->
irq_stat
);
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_WAKEUP_EN_REG
,
timer
->
context
.
twer
);
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_COUNTER_REG
,
...
...
@@ -121,21 +118,13 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
static
void
omap_dm_timer_reset
(
struct
omap_dm_timer
*
timer
)
{
omap_dm_timer_enable
(
timer
);
if
(
timer
->
pdev
->
id
!=
1
)
{
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_IF_CTRL_REG
,
0x06
);
omap_dm_timer_wait_for_reset
(
timer
);
}
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_IF_CTRL_REG
,
0x06
);
omap_dm_timer_wait_for_reset
(
timer
);
__omap_dm_timer_reset
(
timer
,
0
,
0
);
omap_dm_timer_disable
(
timer
);
timer
->
posted
=
1
;
}
int
omap_dm_timer_prepare
(
struct
omap_dm_timer
*
timer
)
{
int
ret
;
/*
* FIXME: OMAP1 devices do not use the clock framework for dmtimers so
* do not call clk_get() for these devices.
...
...
@@ -149,13 +138,15 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
}
}
omap_dm_timer_enable
(
timer
);
if
(
timer
->
capability
&
OMAP_TIMER_NEEDS_RESET
)
omap_dm_timer_reset
(
timer
);
ret
=
omap_dm_timer_set_source
(
timer
,
OMAP_TIMER_SRC_32_KHZ
);
__omap_dm_timer_enable_posted
(
timer
);
omap_dm_timer_disable
(
timer
);
timer
->
posted
=
1
;
return
ret
;
return
omap_dm_timer_set_source
(
timer
,
OMAP_TIMER_SRC_32_KHZ
);
}
static
inline
u32
omap_dm_timer_reserved_systimer
(
int
id
)
...
...
@@ -449,7 +440,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
*/
timer
->
context
.
tclr
=
omap_dm_timer_read_reg
(
timer
,
OMAP_TIMER_CTRL_REG
);
timer
->
context
.
tisr
=
__raw_readl
(
timer
->
irq_stat
);
omap_dm_timer_disable
(
timer
);
return
0
;
}
...
...
@@ -459,7 +449,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int
ret
;
char
*
parent_name
=
NULL
;
struct
clk
*
fclk
,
*
parent
;
struct
clk
*
parent
;
struct
dmtimer_platform_data
*
pdata
;
if
(
unlikely
(
!
timer
))
...
...
@@ -478,11 +468,8 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
if
(
pdata
&&
pdata
->
set_timer_src
)
return
pdata
->
set_timer_src
(
timer
->
pdev
,
source
);
fclk
=
clk_get
(
&
timer
->
pdev
->
dev
,
"fck"
);
if
(
IS_ERR_OR_NULL
(
fclk
))
{
pr_err
(
"%s: fck not found
\n
"
,
__func__
);
if
(
!
timer
->
fclk
)
return
-
EINVAL
;
}
switch
(
source
)
{
case
OMAP_TIMER_SRC_SYS_CLK
:
...
...
@@ -501,18 +488,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
parent
=
clk_get
(
&
timer
->
pdev
->
dev
,
parent_name
);
if
(
IS_ERR_OR_NULL
(
parent
))
{
pr_err
(
"%s: %s not found
\n
"
,
__func__
,
parent_name
);
ret
=
-
EINVAL
;
goto
out
;
return
-
EINVAL
;
}
ret
=
clk_set_parent
(
fclk
,
parent
);
ret
=
clk_set_parent
(
timer
->
fclk
,
parent
);
if
(
IS_ERR_VALUE
(
ret
))
pr_err
(
"%s: failed to set %s as parent
\n
"
,
__func__
,
parent_name
);
clk_put
(
parent
);
out:
clk_put
(
fclk
);
return
ret
;
}
...
...
@@ -595,8 +579,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
l
|=
OMAP_TIMER_CTRL_CE
;
else
l
&=
~
OMAP_TIMER_CTRL_CE
;
omap_dm_timer_write_reg
(
timer
,
OMAP_TIMER_CTRL_REG
,
l
);
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
;
...
...
@@ -672,6 +656,37 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
}
EXPORT_SYMBOL_GPL
(
omap_dm_timer_set_int_enable
);
/**
* omap_dm_timer_set_int_disable - disable timer interrupts
* @timer: pointer to timer handle
* @mask: bit mask of interrupts to be disabled
*
* Disables the specified timer interrupts for a timer.
*/
int
omap_dm_timer_set_int_disable
(
struct
omap_dm_timer
*
timer
,
u32
mask
)
{
u32
l
=
mask
;
if
(
unlikely
(
!
timer
))
return
-
EINVAL
;
omap_dm_timer_enable
(
timer
);
if
(
timer
->
revision
==
1
)
l
=
__raw_readl
(
timer
->
irq_ena
)
&
~
mask
;
__raw_writel
(
l
,
timer
->
irq_dis
);
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
;
}
EXPORT_SYMBOL_GPL
(
omap_dm_timer_set_int_disable
);
unsigned
int
omap_dm_timer_read_status
(
struct
omap_dm_timer
*
timer
)
{
unsigned
int
l
;
...
...
@@ -693,8 +708,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
return
-
EINVAL
;
__omap_dm_timer_write_status
(
timer
,
value
);
/* Save the context */
timer
->
context
.
tisr
=
value
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
omap_dm_timer_write_status
);
...
...
@@ -797,6 +811,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
timer
->
capability
|=
OMAP_TIMER_SECURE
;
}
else
{
timer
->
id
=
pdev
->
id
;
timer
->
errata
=
pdata
->
timer_errata
;
timer
->
capability
=
pdata
->
timer_capability
;
timer
->
reserved
=
omap_dm_timer_reserved_systimer
(
timer
->
id
);
timer
->
get_context_loss_count
=
pdata
->
get_context_loss_count
;
...
...
arch/arm/plat-omap/include/plat/dmtimer.h
View file @
9dc57643
...
...
@@ -32,7 +32,6 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
...
...
@@ -55,6 +54,10 @@
#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01
#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02
/* posted mode types */
#define OMAP_TIMER_NONPOSTED 0x00
#define OMAP_TIMER_POSTED 0x01
/* timer capabilities used in hwmod database */
#define OMAP_TIMER_SECURE 0x80000000
#define OMAP_TIMER_ALWON 0x40000000
...
...
@@ -62,6 +65,16 @@
#define OMAP_TIMER_NEEDS_RESET 0x10000000
#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000
/*
* timer errata flags
*
* Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
* errata prevents us from using posted mode on these devices, unless the
* timer counter register is never read. For more details please refer to
* the OMAP3/4/5 errata documents.
*/
#define OMAP_TIMER_ERRATA_I103_I767 0x80000000
struct
omap_timer_capability_dev_attr
{
u32
timer_capability
;
};
...
...
@@ -70,8 +83,6 @@ struct omap_dm_timer;
struct
timer_regs
{
u32
tidr
;
u32
tistat
;
u32
tisr
;
u32
tier
;
u32
twer
;
u32
tclr
;
...
...
@@ -93,6 +104,7 @@ struct timer_regs {
struct
dmtimer_platform_data
{
/* set_timer_src - Only used for OMAP1 devices */
int
(
*
set_timer_src
)(
struct
platform_device
*
pdev
,
int
source
);
u32
timer_errata
;
u32
timer_capability
;
int
(
*
get_context_loss_count
)(
struct
device
*
);
};
...
...
@@ -122,6 +134,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i
int
omap_dm_timer_set_prescaler
(
struct
omap_dm_timer
*
timer
,
int
prescaler
);
int
omap_dm_timer_set_int_enable
(
struct
omap_dm_timer
*
timer
,
unsigned
int
value
);
int
omap_dm_timer_set_int_disable
(
struct
omap_dm_timer
*
timer
,
u32
mask
);
unsigned
int
omap_dm_timer_read_status
(
struct
omap_dm_timer
*
timer
);
int
omap_dm_timer_write_status
(
struct
omap_dm_timer
*
timer
,
unsigned
int
value
);
...
...
@@ -269,6 +282,7 @@ struct omap_dm_timer {
int
ctx_loss_count
;
int
revision
;
u32
capability
;
u32
errata
;
struct
platform_device
*
pdev
;
struct
list_head
node
;
};
...
...
@@ -307,7 +321,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
OMAP_TIMER_V1_SYS_STAT_OFFSET
;
timer
->
irq_stat
=
timer
->
io_base
+
OMAP_TIMER_V1_STAT_OFFSET
;
timer
->
irq_ena
=
timer
->
io_base
+
OMAP_TIMER_V1_INT_EN_OFFSET
;
timer
->
irq_dis
=
NULL
;
timer
->
irq_dis
=
timer
->
io_base
+
OMAP_TIMER_V1_INT_EN_OFFSET
;
timer
->
pend
=
timer
->
io_base
+
_OMAP_TIMER_WRITE_PEND_OFFSET
;
timer
->
func_base
=
timer
->
io_base
;
}
else
{
...
...
@@ -340,28 +354,46 @@ static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
l
|=
1
<<
2
;
__raw_writel
(
l
,
timer
->
io_base
+
OMAP_TIMER_OCP_CFG_OFFSET
);
/* Match hardware reset default of posted mode */
__omap_dm_timer_write
(
timer
,
OMAP_TIMER_IF_CTRL_REG
,
OMAP_TIMER_CTRL_POSTED
,
0
);
}
static
inline
int
__omap_dm_timer_set_source
(
struct
clk
*
timer_fck
,
struct
clk
*
parent
)
/*
* __omap_dm_timer_enable_posted - enables write posted mode
* @timer: pointer to timer instance handle
*
* Enables the write posted mode for the timer. When posted mode is enabled
* writes to certain timer registers are immediately acknowledged by the
* internal bus and hence prevents stalling the CPU waiting for the write to
* complete. Enabling this feature can improve performance for writing to the
* timer registers.
*/
static
inline
void
__omap_dm_timer_enable_posted
(
struct
omap_dm_timer
*
timer
)
{
int
ret
;
if
(
timer
->
posted
)
return
;
clk_disable
(
timer_fck
);
ret
=
clk_set_parent
(
timer_fck
,
parent
);
clk_enable
(
timer_fck
);
if
(
timer
->
errata
&
OMAP_TIMER_ERRATA_I103_I767
)
return
;
/*
* When the functional clock disappears, too quick writes seem
* to cause an abort. XXX Is this still necessary?
*/
__delay
(
300000
);
__omap_dm_timer_write
(
timer
,
OMAP_TIMER_IF_CTRL_REG
,
OMAP_TIMER_CTRL_POSTED
,
0
);
timer
->
context
.
tsicr
=
OMAP_TIMER_CTRL_POSTED
;
timer
->
posted
=
OMAP_TIMER_POSTED
;
}
return
ret
;
/**
* __omap_dm_timer_override_errata - override errata flags for a timer
* @timer: pointer to timer handle
* @errata: errata flags to be ignored
*
* For a given timer, override a timer errata by clearing the flags
* specified by the errata argument. A specific erratum should only be
* overridden for a timer if the timer is used in such a way the erratum
* has no impact.
*/
static
inline
void
__omap_dm_timer_override_errata
(
struct
omap_dm_timer
*
timer
,
u32
errata
)
{
timer
->
errata
&=
~
errata
;
}
static
inline
void
__omap_dm_timer_stop
(
struct
omap_dm_timer
*
timer
,
...
...
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