Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: OMAP: DMTimer: Optimize by adding load and start

This patch optimizes the timer load and start sequence. By combining the
load and start a needless posted wait can be removed from the system timer
execution path.

* Before patch register writes are taking up .078% @ 500MHz during idle.

Address |total |min |max |avr |count|ratio%
old\process\default_idle|7.369s |0.0us|999.902ms|14.477ms|509. |62.661%
ld\Global\cpu_v7_do_idle|4.265s |0.0us|375.786ms|24.374ms|175. |36.270%
(UNKNOWN)|17.503ms|0.us|531.080us|5.119us|3419. |0.148%
r\omap_dm_timer_set_load|8.135ms|0.0us|79.887us|15.065us|540. |0.069% <--
\vmlinux-old\Global\_end|2.023ms|0.0us|4.000us|0.560us|3613. |0.017%
-old\Global\__raw_readsw|1.962ms|0.0us|108.610us|9.167us|214. |0.016%
old\smc91x\smc_interrupt|1.353ms|0.0us|10.212us|2.348us|576. |0.011%
s/namei\__link_path_walk|1.161ms|0.0us|4.310us|0.762us| 1524. |0.009%
\omap_dm_timer_write_reg|1.085ms|0.0us|126.150us|2.153us|504. |0.009% <--

* After patch timer functions do not show up in top listings for long captures.

Signed-off-by: Richard Woodruff <r-woodruff2@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

authored by

Richard Woodruff and committed by
Tony Lindgren
3fddd09e 0f0d0807

+22 -7
+3 -6
arch/arm/mach-omap2/timer-gp.c
··· 59 59 static int omap2_gp_timer_set_next_event(unsigned long cycles, 60 60 struct clock_event_device *evt) 61 61 { 62 - omap_dm_timer_set_load(gptimer, 0, 0xffffffff - cycles); 63 - omap_dm_timer_start(gptimer); 62 + omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles); 64 63 65 64 return 0; 66 65 } ··· 76 77 period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; 77 78 period -= 1; 78 79 79 - omap_dm_timer_set_load(gptimer, 1, 0xffffffff - period); 80 - omap_dm_timer_start(gptimer); 80 + omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); 81 81 break; 82 82 case CLOCK_EVT_MODE_ONESHOT: 83 83 break; ··· 170 172 tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt)); 171 173 tick_period = (tick_rate / HZ) - 1; 172 174 173 - omap_dm_timer_set_load(gpt, 1, 0); 174 - omap_dm_timer_start(gpt); 175 + omap_dm_timer_set_load_start(gpt, 1, 0); 175 176 176 177 clocksource_gpt.mult = 177 178 clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
+18 -1
arch/arm/plat-omap/dmtimer.c
··· 546 546 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); 547 547 } 548 548 549 + /* Optimized set_load which removes costly spin wait in timer_start */ 550 + void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, 551 + unsigned int load) 552 + { 553 + u32 l; 554 + 555 + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 556 + if (autoreload) 557 + l |= OMAP_TIMER_CTRL_AR; 558 + else 559 + l &= ~OMAP_TIMER_CTRL_AR; 560 + l |= OMAP_TIMER_CTRL_ST; 561 + 562 + omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); 563 + omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 564 + omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 565 + } 566 + 549 567 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, 550 568 unsigned int match) 551 569 { ··· 577 559 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 578 560 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 579 561 } 580 - 581 562 582 563 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, 583 564 int toggle, int trigger)
+1
include/asm-arm/arch-omap/dmtimer.h
··· 66 66 67 67 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); 68 68 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); 69 + void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value); 69 70 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); 70 71 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); 71 72 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);