ARM: OMAP: DMTIMER fixes
Subsystems (4)
v3 cover ARM: OMAP: DMTIMER fixes
This series includes several fixes for the OMAP DMTIMER driver. This is based upon Tony Lindgren's current master branch [1].
Tested on OMAP5912 OSK, OMAP2420 H4, OMAP3430 Beagle and OMAP4430 Panda. Testing includes ...
1. Booting kernel on above boards
2. Set date and ensuring time of day is correct after 24 hours
3. Checking the timer counter is incrementing when configuring and starting a timer
4. Checking the timer overflow interrupt when timer expires.
5. Using different clock sources to operate the timer with.
6. Running a loop test overnight that continually runs test #3 and #4 for each available timer
This has also been boot tested on the AM335x Beagle Bone.
V3 changes:
- Combined patches #2 and #3 in version 2 series into single patch.
- Updated errata i103/i767 workaround to pass errata information via platform data to avoid using cpu_is_xxxx() macros in dmtimer driver.
[1] http://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
Jon Hunter (13):
ARM: OMAP: Add DMTIMER definitions for posted mode
ARM: OMAP3+: Implement timer workaround for errata i103 and i767
ARM: OMAP: Fix timer posted mode support
ARM: OMAP3: Correct HWMOD DMTIMER SYSC register declarations
ARM: OMAP2/3: Define HWMOD software reset status for DMTIMERs
ARM: OMAP2+: Don't use __omap_dm_timer_reset()
ARM: OMAP: Fix dmtimer reset for timer1
ARM: OMAP: Don't restore of DMTIMER TISTAT register
ARM: OMAP: Don't restore DMTIMER interrupt status register
ARM: OMAP: Fix spurious interrupts when using timer match feature
ARM: OMAP: Add dmtimer interrupt disable function
ARM: OMAP: Remove unnecessary call to clk_get()
ARM: OMAP: Remove __omap_dm_timer_set_source function
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 15 +++- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 41 +++++------ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 + arch/arm/mach-omap2/timer.c | 70 +++++++++++++----- arch/arm/plat-omap/dmtimer.c | 77 ++++++++++++-------- arch/arm/plat-omap/include/plat/dmtimer.h | 72 +++++++++++++----- 6 files changed, 188 insertions(+), 91 deletions(-)
Signature · 1 line
1.7.9.5
PATCH v3 1/13 ARM: OMAP: Add DMTIMER definitions for posted mode
For OMAP2+ devices, when using DMTIMERs for system timers (clock-events and clock-source) the posted mode configuration of the timers is used. To allow the compiler to optimise the functions for configuring and reading the system timers, the posted flag variable is hard-coded with the value 1. To make it clear that posted mode is being used add some definitions so that it is more readable.
--- arch/arm/mach-omap2/timer.c | 17 ++++++++++------- arch/arm/plat-omap/include/plat/dmtimer.h | 4 ++++ 2 files changed, 14 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/timer.c +10 -7
@@ -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 ;
@@ -359,7 +359,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_POSTED ); }static struct clocksource clocksource_gpt = {
@@ -373,7 +374,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_POSTED );return 0 ; }
@@ -455,7 +457,8 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,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_POSTED );setup_sched_clock (dmtimer_read_sched_clock,32 , clksrc.rate);if (clocksource_register_hz (&clocksource_gpt, clksrc.rate))
arch/arm/plat-omap/include/plat/dmtimer.h +4 -0
@@ -55,6 +55,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
Signature · 1 line
1.7.9.5
PATCH v3 2/13 ARM: OMAP3+: Implement timer workaround for errata i103 and i767
In reply to Jon HunterErrata Titles:
i103: Delay needed to read some GP timer, WD timer and sync timer
registers after wakeup (OMAP3/4)
i767: Delay needed to read some GP timer registers after wakeup (OMAP5)
Description (i103/i767):
If a General Purpose Timer (GPTimer) is in posted mode (TSICR [2].POSTED=1), due to internal resynchronizations, values read in TCRR, TCAR1 and TCAR2 registers right after the timer interface clock (L4) goes from stopped to active may not return the expected values. The most common event leading to this situation occurs upon wake up from idle.
GPTimer non-posted synchronization mode is not impacted by this limitation.
Workarounds:
1). Disable posted mode
2). Use static dependency between timer clock domain and MPUSS clock
domain
3). Use no-idle mode when the timer is active
Workarounds #2 and #3 are not pratical from a power standpoint and so workaround #1 has been implemented. Disabling posted mode adds some CPU overhead for configuring and reading the timers as the CPU has to wait for accesses to be re-synchronised within the timer. However, disabling posted mode guarantees correct operation.
Please note that it is safe to use posted mode for timers if the counter (TCRR) and capture (TCARx) registers will never be read. An example of this is the clock-event system timer. This is used by the kernel to schedule events however, the timers counter is never read and capture registers are not used. Given that the kernel configures this timer often yet never reads the counter register it is safe to enable posted mode in this case. Hence, for the timer used for kernel clock-events, posted mode is enabled by overriding the errata for devices that are impacted by this defect.
For drivers using the timers that do not read the counter or capture registers and wish to use posted mode, can override the errata and enable posted mode by making the following function calls.
__omap_dm_timer_override_errata(timer, OMAP_TIMER_ERRATA_I103_I767); __omap_dm_timer_enable_posted(timer);
Both dmtimers and watchdogs are impacted by this defect this patch only implements the workaround for the dmtimer. Currently the watchdog driver does not read the counter register and so no workaround is necessary.
Posted mode will be disabled for all OMAP2+ devices (including AM33xx) using a GP timer as a clock-source timer to guarantee correct operation. This is not necessary for OMAP24xx devices but the default clock-source timer for OMAP24xx devices is the 32k-sync timer and not the GP timer and so should not have any impact. This should be re-visited for future devices if this errata is fixed.
Confirmed with Vaibhav Hiremath that this bug also impacts AM33xx devices.
--- arch/arm/mach-omap2/timer.c | 49 ++++++++++++++++++++++----- arch/arm/plat-omap/dmtimer.c | 3 +- arch/arm/plat-omap/include/plat/dmtimer.h | 52 +++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 11 deletions(-)
arch/arm/mach-omap2/timer.c +41 -8
@@ -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;
@@ -311,10 +325,15 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, }__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 +345,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;
@@ -360,7 +389,7 @@ static bool use_gptimer_clksrc;static cycle_t clocksource_read_cycles (struct clocksource *cs) {return (cycle_t )__omap_dm_timer_read_counter (&clksrc, -OMAP_TIMER_POSTED ); +OMAP_TIMER_NONPOSTED ); }static struct clocksource clocksource_gpt = {
@@ -375,7 +404,7 @@ static u32 notrace dmtimer_read_sched_clock(void) {if (clksrc.reserved)return __omap_dm_timer_read_counter (&clksrc, -OMAP_TIMER_POSTED ); +OMAP_TIMER_NONPOSTED );return 0 ; }
@@ -453,12 +482,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 , -OMAP_TIMER_POSTED ); +OMAP_TIMER_NONPOSTED );setup_sched_clock (dmtimer_read_sched_clock,32 , clksrc.rate);if (clocksource_register_hz (&clocksource_gpt, clksrc.rate))
@@ -696,6 +728,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 +2 -1
@@ -128,8 +128,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) }__omap_dm_timer_reset (timer,0 ,0 ); +__omap_dm_timer_enable_posted (timer);omap_dm_timer_disable (timer); - timer->posted =1 ; }int omap_dm_timer_prepare (struct omap_dm_timer *timer)
@@ -797,6 +797,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 +50 -2
78 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v3 3/13 ARM: OMAP: Fix timer posted mode support
In reply to Jon HunterCurrently the dmtimer posted mode is being enabled when the function omap_dm_timer_enable_posted() is called. This function is only being called for OMAP1 timers and OMAP2+ timers that are being used as system timers. Hence, for OMAP2+ timers that are NOT being used as a system timer, posted mode is not enabled but the "timer->posted" variable is still set (incorrectly) in the omap_dm_timer_prepare() function.
This is a regression introduced by commit 3392cdd3 (ARM: OMAP: dmtimer:
switch-over to platform device driver) which was before the omap_dm_timer_enable_posted() function was introduced. Although this is a regression from the original code it only impacts performance and so is not needed for stable.
--- arch/arm/plat-omap/dmtimer.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
arch/arm/plat-omap/dmtimer.c +5 -8
@@ -121,21 +121,16 @@ 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_reset (timer,0 ,0 ); -__omap_dm_timer_enable_posted (timer); -omap_dm_timer_disable (timer); }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 +144,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)
Signature · 1 line
1.7.9.5
PATCH v3 4/13 ARM: OMAP3: Correct HWMOD DMTIMER SYSC register declarations
In reply to Jon HunterCurrently, the OMAP3 HWMOD data defines two TIOCP_CFG register structures (referred to as the SYSC register in the HWMOD data) where timers 1, 2 and 10 use one of the defintions and the other timers use the other definition. For OMAP3 devices the structure of the DMTIMER TIOCP_CFG register is the same for all 12 instances of the DMTIMER. Please note that this is a difference between OMAP3 and OMAP4 and could be the source of the confusion.
For OMAP3 devices, the DMTIMER TIOCP_CFG register has the fields, clock-activity, emufree, idlemode, enwakeup, softreset and autoidle for all 12 timers. Therefore, remove one of the SYSC register definitions for the DMTIMERs and ensure the appropriate register fields are defined for all DMTIMERs.
--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +6 -21
@@ -153,28 +153,13 @@ 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 ), .idlemodes = (SIDLE_FORCE |SIDLE_NO |SIDLE_SMART ), .sysc_fields = &omap_hwmod_sysc_type1, };
@@ -224,7 +209,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = { }, }, .dev_attr = &capability_alwon_dev_attr, - .class = &omap3xxx_timer_1ms_hwmod_class, + .class = &omap3xxx_timer_hwmod_class, };/* timer2 */
@@ -241,7 +226,7 @@ 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, };/* timer3 */
@@ -383,7 +368,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = { }, }, .dev_attr = &capability_pwm_dev_attr, - .class = &omap3xxx_timer_1ms_hwmod_class, + .class = &omap3xxx_timer_hwmod_class, };/* timer11 */
Signature · 1 line
1.7.9.5
PATCH v3 5/13 ARM: OMAP2/3: Define HWMOD software reset status for DMTIMERs
In reply to Jon HunterFor OMAP2/3 devices, the HWMOD data does not define a software reset status field for the DMTIMERs. Therefore, when HWMOD performs a soft-reset of the DMTIMER we don't check and wait for the reset to complete. For OMAP2/3 devices, the software reset status for a DMTIMER can be read from bit 0 of the DMTIMER TISTAT register (referred to as the SYSS register in HWMOD). Add the appropriate HWMOD definitions so that HWMOD will check the software reset status when performing a software reset of the DMTIMER.
--- arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +1 -1
@@ -58,7 +58,7 @@ 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), .sysc_fields = &omap_hwmod_sysc_type1, };
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +2 -1
@@ -159,7 +159,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = { .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_SIDLEMODE |SYSC_HAS_CLOCKACTIVITY |SYSC_HAS_ENAWAKEUP |SYSC_HAS_SOFTRESET | - SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE), +SYSC_HAS_EMUFREE |SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, };
Signature · 1 line
1.7.9.5
PATCH v3 6/13 ARM: OMAP2+: Don't use __omap_dm_timer_reset()
In reply to Jon HunterCurrently OMAP2+ devices are using the function __omap_dm_timer_reset() to configure the clock-activity, idle, wakeup-enable and auto-idle fields in the timer OCP_CFG register. The name of the function is mis-leading because this function does not actually perform a reset of the timer.
For OMAP2+ devices, HWMOD is responsible for reseting and configuring the timer OCP_CFG register. Therefore, do not use __omap_dm_timer_reset() for OMAP2+ devices and rely on HWMOD. Furthermore, some timer instances do not have the fields clock-activity, wakeup-enable and auto-idle and so this function could configure the OCP_CFG register incorrectly.
Currently HWMOD is not configuring the clock-activity field in the OCP_CFG register for timers that have this field. Commit 0f0d080 (ARM: OMAP: DMTimer:
Use posted mode) configures the clock-activity field to keep the f-clk enabled so that the wake-up capability is enabled. Therefore, add the appropriate flags to the timer HWMOD structures to configure this field in the same way.
For OMAP2/3 devices all dmtimers have the clock-activity field, where as for OMAP4 devices, only dmtimer 1, 2 and 10 have the clock-activity field.
Verified on OMAP2420 H4, OMAP3430 Beagle and OMAP4430 Panda that HWMOD is configuring the dmtimer OCP_CFG register as expected for clock-events timer.
--- arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 13 +++++++++++++ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 13 +++++++++++++ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 ++++ arch/arm/mach-omap2/timer.c | 1 - 4 files changed, 30 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +13 -0
@@ -60,6 +60,7 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {SYSC_HAS_ENAWAKEUP |SYSC_HAS_SOFTRESET | 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 +13 -0
@@ -162,6 +162,7 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {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, };
@@ -211,6 +212,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = { }, .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, + .flags = HWMOD_SET_DEFAULT_CLOCKACT, };/* timer2 */
@@ -228,6 +230,7 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = { }, }, .class = &omap3xxx_timer_hwmod_class, + .flags = HWMOD_SET_DEFAULT_CLOCKACT, };/* timer3 */
@@ -245,6 +248,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = { }, }, .class = &omap3xxx_timer_hwmod_class, + .flags = HWMOD_SET_DEFAULT_CLOCKACT, };/* timer4 */
@@ -262,6 +266,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = { }, }, .class = &omap3xxx_timer_hwmod_class, + .flags = HWMOD_SET_DEFAULT_CLOCKACT, };/* timer5 */
@@ -280,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 */
@@ -298,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 */
@@ -316,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 */
@@ -334,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 */
@@ -352,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 */
@@ -370,6 +380,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = { }, .dev_attr = &capability_pwm_dev_attr, .class = &omap3xxx_timer_hwmod_class, + .flags = HWMOD_SET_DEFAULT_CLOCKACT, };/* timer11 */
@@ -388,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 */
@@ -411,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 +4 -0
@@ -3075,6 +3075,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, };
@@ -3128,6 +3129,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 = {
@@ -3150,6 +3152,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 = {
@@ -3324,6 +3327,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 +0 -1
@@ -324,7 +324,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, } }__omap_dm_timer_init_regs (timer); -__omap_dm_timer_reset (timer,1 ,1 );if (posted)__omap_dm_timer_enable_posted (timer);
Signature · 1 line
1.7.9.5
PATCH v3 7/13 ARM: OMAP: Fix dmtimer reset for timer1
In reply to Jon HunterIn commit e32f7ec2 (ARM: OMAP: Fix 32 kHz timer and modify GP timer to use GPT1) a fix was added to prevent timer1 being reset in the function omap_dm_timer_reset() because timer1 was being used as the system timer for OMAP2 devices. Although timer1 is still used by most OMAP2+ devices as a system timer, the function omap_dm_timer_reset() is now only being called for OMAP1 devices and OMAP1 does not use timer1 as a system timer. Therefore, remove the check in omap_dm_timer_reset() so that timer1 is reset for OMAP1 devices.
--- arch/arm/plat-omap/dmtimer.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
arch/arm/plat-omap/dmtimer.c +2 -5
@@ -121,11 +121,8 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)static void omap_dm_timer_reset (struct omap_dm_timer *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 ); }
Signature · 1 line
1.7.9.5
PATCH v3 8/13 ARM: OMAP: Don't restore of DMTIMER TISTAT register
In reply to Jon HunterThe timer TISTAT register is a read-only register and therefore restoring the context is not needed. Furthermore, the context of TISTAT is never saved anywhere in the current code. The TISTAT register is read-only for all OMAP devices from OMAP1 to OMAP4. OMAP5 timers no longer have this register.
--- arch/arm/plat-omap/dmtimer.c | 3 --- arch/arm/plat-omap/include/plat/dmtimer.h | 1 - 2 files changed, 4 deletions(-)
arch/arm/plat-omap/dmtimer.c +0 -3
@@ -83,9 +83,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);
arch/arm/plat-omap/include/plat/dmtimer.h +0 -1
@@ -84,7 +84,6 @@ struct omap_dm_timer;struct timer_regs {u32 tidr; -u32 tistat;u32 tisr;u32 tier;u32 twer;
Signature · 1 line
1.7.9.5
PATCH v3 9/13 ARM: OMAP: Don't restore DMTIMER interrupt status register
In reply to Jon HunterRestoring the timer interrupt status is not possible because writing a 1 to any bit in the register clears that bit if set and writing a 0 has no affect. Furthermore, if an interrupt is pending when someone attempts to disable a timer, the timer will fail to transition to the idle state and hence it's context will not be lost. Users should take care to service all interrupts before disabling the timer.
--- arch/arm/plat-omap/dmtimer.c | 5 +---- arch/arm/plat-omap/include/plat/dmtimer.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-)
arch/arm/plat-omap/dmtimer.c +1 -4
@@ -83,7 +83,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) { -__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,
@@ -440,7 +439,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 ; }
@@ -684,8 +682,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);
arch/arm/plat-omap/include/plat/dmtimer.h +0 -1
@@ -84,7 +84,6 @@ struct omap_dm_timer;struct timer_regs {u32 tidr; -u32 tisr;u32 tier;u32 twer;u32 tclr;
Signature · 1 line
1.7.9.5
PATCH v3 10/13 ARM: OMAP: Fix spurious interrupts when using timer match feature
In reply to Jon HunterThe OMAP DMTIMERs can generate an interrupt when the timer counter value matches the value stored in the timer's match register. When using this feature spurious interrupts were seen, because the compare logic is being enabled before the match value is loaded and according to the documentation the match value must be loaded before the compare logic is enable.
The reset value for the timer counter and match registers is 0 and hence, by enabling the compare logic before the actual match value is loaded a spurious interrupt can be generated as the reset values match.
--- arch/arm/plat-omap/dmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/plat-omap/dmtimer.c +1 -1
@@ -584,8 +584,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;
Signature · 1 line
1.7.9.5
PATCH v3 11/13 ARM: OMAP: Add dmtimer interrupt disable function
In reply to Jon HunterThe OMAP dmtimer driver does not currently have a function to disable the timer interrupts. For some timer instances the timer interrupt enable function can be used to disable the interrupts because the same interrupt enable register is used to disable interrupts. However, some timer instances have separate interrupt enable/disable registers and so this will not work. Therefore, add a dedicated function to disable interrupts.
This change is required for OMAP4+ devices. For OMAP4, all timers apart from 1, 2 and 10 need this function and for OMAP5 all timers need this function. Please note that the interrupt disable function has been written so that it can be used by all OMAP devices.
--- arch/arm/plat-omap/dmtimer.c | 31 +++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/dmtimer.h | 3 ++- 2 files changed, 33 insertions(+), 1 deletion(-)
arch/arm/plat-omap/dmtimer.c +31 -0
@@ -661,6 +661,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;
arch/arm/plat-omap/include/plat/dmtimer.h +2 -1
@@ -135,6 +135,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, iint 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);
@@ -321,7 +322,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 {
Signature · 1 line
1.7.9.5
PATCH v3 12/13 ARM: OMAP: Remove unnecessary call to clk_get()
In reply to Jon HunterWhenever we call the function omap_dm_timer_set_source() to set the clock source of a dmtimer we look-up the dmtimer functional clock source by calling clk_get(). This is not necessary because on requesting a dmtimer we look-up the functional clock source and store it in the omap_dm_timer structure. So instead of looking up the clock again used the clock handle that stored in the omap_dm_timer structure.
--- arch/arm/plat-omap/dmtimer.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
arch/arm/plat-omap/dmtimer.c +4 -10
@@ -448,7 +448,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))
@@ -467,11 +467,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 :
@@ -490,18 +487,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; }
Signature · 1 line
1.7.9.5
PATCH v3 13/13 ARM: OMAP: Remove __omap_dm_timer_set_source function
In reply to Jon HunterThe __omap_dm_timer_set_source() function is only used by the system timer (clock-events and clock-source) code for OMAP2+ devices. Therefore, we can remove this code from the dmtimer driver and move it to the system timer code for OMAP2+ devices.
The current __omap_dm_timer_set_source() function calls clk_disable() before calling clk_set_parent() and clk_enable() afterwards. We can avoid these calls to clk_disable/enable by moving the calls to omap_hwmod_setup_one() and omap_hwmod_enable() to after the call to clk_set_parent() in omap_dm_timer_init_one().
The function omap_hwmod_setup_one() will enable the timers functional clock and therefore increment the use-count of the functional clock to 1. clk_set_parent() will fail if the use-count is not 0 when called. Hence, if omap_hwmod_setup_one() is called before clk_set_parent(), we will need to call clk_disable() before calling clk_set_parent() to decrement the use-count. Hence, avoid these extra calls to disable and enable the functional clock by moving the calls to omap_hwmod_setup_one() and omap_hwmod_enable() to after clk_set_parent().
We can also remove the delay from the __omap_dm_timer_set_source() function because enabling the clock will now be handled via the HWMOD framework by calling omap_hwmod_setup_one(). Therefore, by moving the calls to omap_hwmod_setup_one() and omap_hwmod_enable() to after the call to clk_set_parent(), we can simply replace __omap_dm_timer_set_source() with clk_set_parent().
It should be safe to move these hwmod calls to later in the omap_dm_timer_init_one() because other calls to the hwmod layer that occur before are just requesting resource information.
Testing includes boot testing on OMAP2420 H4, OMAP3430 SDP and OMAP4430 Blaze with the following configurations:
1. CONFIG_OMAP_32K_TIMER=y
2. CONFIG_OMAP_32K_TIMER=y and boot parameter "clocksource=gp_timer"
3. CONFIG_OMAP_32K_TIMER not set
4. CONFIG_OMAP_32K_TIMER not set and boot parameter "clocksource=gp_timer"
--- arch/arm/mach-omap2/timer.c | 9 ++++----- arch/arm/plat-omap/dmtimer.c | 1 + arch/arm/plat-omap/include/plat/dmtimer.h | 19 ------------------- 3 files changed, 5 insertions(+), 24 deletions(-)
arch/arm/mach-omap2/timer.c +4 -5
@@ -274,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 ;
@@ -306,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;
@@ -316,13 +312,16 @@ 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);if (posted)
arch/arm/plat-omap/dmtimer.c +1 -0
@@ -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>
arch/arm/plat-omap/include/plat/dmtimer.h +0 -19
@@ -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>
@@ -397,24 +396,6 @@ static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer, timer->errata &= ~errata; } -static inline int __omap_dm_timer_set_source (struct clk *timer_fck, -struct clk *parent) -{ -int ret; - -clk_disable (timer_fck); - ret =clk_set_parent (timer_fck, parent); -clk_enable (timer_fck); - -/* -* When the functional clock disappears, too quick writes seem -* to cause an abort. XXX Is this still necessary? -*/ -__delay (300000 ); - -return ret; -} -static inline void __omap_dm_timer_stop (struct omap_dm_timer *timer,int posted,unsigned long rate) {
Signature · 1 line
1.7.9.5
Tony Lindgren
maintainerv3 cover ARM: OMAP: DMTIMER fixes
In reply to Jon HunterQuoted 2 lines · Jon Hunter
This series includes several fixes for the OMAP DMTIMER driver. This is based upon Tony Lindgren's current master branch [1].
You should be able to use omap-for-v3.8/dt as the base now with the cleanup merged there. The master branch is just a merge of the various topic branches, and can't be used as a base for pull requests.
Regards,
Tony
Quoted 1 line
[1] http://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
v3 cover ARM: OMAP: DMTIMER fixes
Quoted 7 lines · Tony Lindgren
Quoted 2 lines · Jon Hunter
This series includes several fixes for the OMAP DMTIMER driver. This is based upon Tony Lindgren's current master branch [1].
You should be able to use omap-for-v3.8/dt as the base now with the cleanup merged there. The master branch is just a merge of the various topic branches, and can't be used as a base for pull requests.
Ok, great will base on top of that branch.
Cheers
Jon