void timer_monotonic_get(struct mono_time *mt) { uint32_t current_tick; uint32_t usecs_elapsed; uint32_t timer_fsb; if (!mono_counter.initialized) { init_timer(); timer_fsb = get_timer_fsb(); /* An FSB frequency of 200Mhz provides a 20 second polling * interval between timer_monotonic_get() calls before wrap * around occurs. */ if (timer_fsb > 200) printk(BIOS_WARNING, "apic timer freq (%d) may be too fast.\n", timer_fsb); mono_counter.last_value = lapic_read(LAPIC_TMCCT); mono_counter.initialized = 1; } timer_fsb = get_timer_fsb(); current_tick = lapic_read(LAPIC_TMCCT); /* Note that the APIC timer counts down. */ usecs_elapsed = (mono_counter.last_value - current_tick) / timer_fsb; /* Update current time and tick values only if a full tick occurred. */ if (usecs_elapsed) { mono_time_add_usecs(&mono_counter.time, usecs_elapsed); mono_counter.last_value = current_tick; } /* Save result. */ *mt = mono_counter.time; }
void timer_monotonic_get(struct mono_time *mt) { uint64_t current_tick; uint64_t ticks_elapsed; if (!mono_counter.initialized) { init_timer(); mono_counter.last_value = rdtscll(); mono_counter.initialized = 1; } current_tick = rdtscll(); ticks_elapsed = current_tick - mono_counter.last_value; /* Update current time and tick values only if a full tick occurred. */ if (ticks_elapsed >= clocks_per_usec) { uint64_t usecs_elapsed; usecs_elapsed = ticks_elapsed / clocks_per_usec; mono_time_add_usecs(&mono_counter.time, (long)usecs_elapsed); mono_counter.last_value = current_tick; } /* Save result. */ *mt = mono_counter.time; }
void timer_monotonic_get(struct mono_time *mt) { uint64_t current_tick; uint64_t ticks_elapsed; unsigned long ticks_per_usec; struct monotonic_counter *mono_counter; mono_counter = get_monotonic_context(); if (!mono_counter->initialized) { init_timer(); mono_counter->last_value = rdtscll(); mono_counter->initialized = 1; } current_tick = rdtscll(); ticks_elapsed = current_tick - mono_counter->last_value; ticks_per_usec = get_clocks_per_usec(); /* Update current time and tick values only if a full tick occurred. */ if (ticks_elapsed >= ticks_per_usec) { uint64_t usecs_elapsed; usecs_elapsed = ticks_elapsed / ticks_per_usec; mono_time_add_usecs(&mono_counter->time, (long)usecs_elapsed); mono_counter->last_value = current_tick; } /* Save result. */ *mt = mono_counter->time; }
/* * Configure DP in slave mode and wait for video stream. * * param dp pointer to main s5p-dp structure * param video_info pointer to main video_info structure. * return status */ static int s5p_dp_config_video(struct s5p_dp_device *dp, struct video_info *video_info) { int timeout = 0; struct exynos5_dp *base = dp->base; struct mono_time start, current, end; s5p_dp_config_video_slave_mode(dp, video_info); s5p_dp_set_video_color_format(dp, video_info->color_depth, video_info->color_space, video_info->dynamic_range, video_info->ycbcr_coeff); if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { printk(BIOS_DEBUG, "PLL is not locked yet.\n"); return -ERR_PLL_NOT_UNLOCKED; } timer_monotonic_get(&start); end = current = start; mono_time_add_usecs(&end, STREAM_ON_TIMEOUT * USECS_PER_MSEC); do { if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) { timeout++; break; } timer_monotonic_get(¤t); } while (mono_time_before(¤t, &end)); if (!timeout) { printk(BIOS_ERR, "Video Clock Not ok after %ldus.\n", mono_time_diff_microseconds(&start, &end)); return -ERR_VIDEO_CLOCK_BAD; } /* Set to use the register calculated M/N video */ s5p_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); clrbits_le32(&base->video_ctl_10, FORMAT_SEL); /* Disable video mute */ clrbits_le32(&base->video_ctl_1, HDCP_VIDEO_MUTE); /* Configure video slave mode */ s5p_dp_enable_video_master(dp); /* Enable video */ setbits_le32(&base->video_ctl_1, VIDEO_EN); timeout = s5p_dp_is_video_stream_on(dp); if (timeout) { printk(BIOS_DEBUG, "Video Stream Not on\n"); return -ERR_VIDEO_STREAM_BAD; } return 0; }
/* delay x useconds */ void udelay(unsigned usec) { struct mono_time current, end; if (!thread_yield_microseconds(usec)) return; timer_monotonic_get(¤t); end = current; mono_time_add_usecs(&end, usec); if (mono_time_after(¤t, &end)) { printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n", usec); /* There's not much we can do if usec is too big. Use a long, * paranoid delay value and hope for the best... */ end = current; mono_time_add_usecs(&end, USECS_PER_SEC); } while (mono_time_before(¤t, &end)) timer_monotonic_get(¤t); }
void timer_monotonic_get(struct mono_time *mt) { uint32_t current_tick; uint32_t usecs_elapsed; if (!mono_counter.initialized) { mono_counter.last_value = read_counter_msr(); mono_counter.initialized = 1; } current_tick = read_counter_msr(); usecs_elapsed = (current_tick - mono_counter.last_value) / 24; /* Update current time and tick values only if a full tick occurred. */ if (usecs_elapsed) { mono_time_add_usecs(&mono_counter.time, usecs_elapsed); mono_counter.last_value = current_tick; } /* Save result. */ *mt = mono_counter.time; }