hi Viresh: 2015-09-01 11:57 GMT+08:00 Viresh Kumar <viresh.kumar@xxxxxxxxxx>: > On Mon, Aug 31, 2015 at 7:33 PM, vichy <vichy.kuo@xxxxxxxxx> wrote: >> hi all: >> My platform is like below: >> 1. single core Cortex A9 >> 2. use global timer for system timer >> >> after I porting cpu frequency driver based on snow ball, the cpu >> frequency did change as I expected. >> But the system time is incorrect( since pherial clk is got from cpu frequency) >> >> for example: >> a) cpu 1G (pherial clk = 250M) --> sleep 1 sec (OK) >> b) cpu 500M (pherial clk = 125M) --> sleep 1 sec (will be measured as 2 sec) >> >> I try to call below 2 functions to change the frequency of clocksource >> and clockevent, but the above b) sleep time is still incorrect when >> cpu runs in 500Mhz. >> clockevents_update_freq(this_cpu_ptr(gt_evt), gt_clk_rate); >> __clocksource_updatefreq_hz(>_clocksource, gt_clk_rate); >> >> in Arm cortex A9 single core system with Global timer as system timer, >> is there any kernel api to change system timer period when cpu/pherial >> frequency change? >> >> appreciate your kind help in advance, > > The list cpufreq@xxxxxxxxxxxxxxx is the wrong list for posting cpufreq queries > as we have moved to Linux PM list <linux-pm@xxxxxxxxxxxxxxx> list now. > > Try unsetting CPUFREQ_CONST_LOOPS flag in your driver, if you have it > set. I DIDN'T set the CPUFREQ_CONST_LOOPS when I register my cpufreq driver I pasted my cpufreq driver declariation as below: static struct cpufreq_driver plat_cpufreq_driver = { .flags = CPUFREQ_STICKY, .verify = plat_cpufreq_verify_speed, .target = plat_cpufreq_target, .get = plat_cpufreq_getspeed, .init = plat_cpufreq_init, .name = "plat-cpufreq", .attr = plat_cpufreq_attr, }; I have traced the kernel code if I guess correctly, the sleep accurate is based on jiffies and tick_handle_periodic will periodically update the next event interval void tick_handle_periodic --> for (;;) { if (!clockevents_program_event(dev, next, false)) return; /* * Have to be careful here. If we're in oneshot mode, * before we call tick_periodic() in a loop, we need * to be sure we're using a real hardware clocksource. * Otherwise we could get trapped in an infinite * loop, as the tick_periodic() increments jiffies, * when then will increment time, posibly causing * the loop to trigger again and again. */ if (timekeeping_valid_for_hres()) tick_periodic(cpu); next = ktime_add(next, tick_period); } and in clockevents_program_event, we will use mult, shift to calculate the cycles need for global timer triggering next interrupt event. clc = ((unsigned long long) delta * dev->mult) >> dev->shift; rc = dev->set_next_event((unsigned long) clc, dev); belwo is my tick device information in /proc/timer_list and multi did change to 1/2 when I change cpu freq from 1G to 500Mhz. when cpu run 1GHz except multi and shift, is there any place I need to take care for system timer accurate? appreciate your kind help, Tick Device: mode: 1 Per CPU device: 0 Clock Event Device: arm_global_timer max_delta_ns: 17043521021 min_delta_ns: 1000 mult: 541165879 shift: 31 mode: 3 next_event: 2176344000000 nsecs set_next_event: gt_clockevent_set_next_event set_mode: gt_clockevent_set_mode event_handler: hrtimer_interrupt retries: 0 when cpu run in 500Mhz Tick Device: mode: 1 Per CPU device: 0 Clock Event Device: arm_global_timer max_delta_ns: 34087041979 min_delta_ns: 1000 mult: 270582940 shift: 31 mode: 3 next_event: 2230100000000 nsecs set_next_event: gt_clockevent_set_next_event set_mode: gt_clockevent_set_mode event_handler: hrtimer_interrupt retries: 0 -- To unsubscribe from this list: send the line "unsubscribe cpufreq" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html