arch/hexagon/kernel/time.c

Source file repositories/reference/linux-study-clean/arch/hexagon/kernel/time.c

File Facts

System
Linux kernel
Corpus path
arch/hexagon/kernel/time.c
Extension
.c
Size
6027 bytes
Lines
234
Domain
Architecture Layer
Bucket
arch/hexagon
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

* time_init_deferred - called by start_kernel to set up timer/clock source
 *
 * Install the IRQ handler for the clock, setup timers.
 * This is done late, as that way, we can use ioremap().
 *
 * This runs just before the delay loop is calibrated, and
 * is used for delay calibration.
 */
static void __init time_init_deferred(void)
{
	struct resource *resource = NULL;
	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
	unsigned long flag = IRQF_TIMER | IRQF_TRIGGER_RISING;

	ce_dev->cpumask = cpu_all_mask;

	resource = rtos_timer_device.resource;

	/*  ioremap here means this has to run later, after paging init  */
	rtos_timer = ioremap(resource->start, resource_size(resource));

	if (!rtos_timer) {
		release_mem_region(resource->start, resource_size(resource));
	}
	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);

	/*  Note: the sim generic RTOS clock is apparently really 18750Hz  */

	/*
	 * Last arg is some guaranteed seconds for which the conversion will
	 * work without overflow.
	 */
	clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);

	ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
	ce_dev->max_delta_ticks = 0x7fffffff;
	ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
	ce_dev->min_delta_ticks = 0xf;

#ifdef CONFIG_SMP
	setup_percpu_clockdev();
#endif

	clockevents_register_device(ce_dev);
	if (request_irq(ce_dev->irq, timer_interrupt, flag, "rtos_timer", NULL))
		pr_err("Failed to register rtos_timer interrupt\n");
}

void __init time_init(void)
{
	late_time_init = time_init_deferred;
}

void __delay(unsigned long cycles)
{
	unsigned long long start = __vmgettime();

	while ((__vmgettime() - start) < cycles)
		cpu_relax();
}
EXPORT_SYMBOL(__delay);

/*
 * This could become parametric or perhaps even computed at run-time,
 * but for now we take the observed simulator jitter.
 */
static long long fudgefactor = 350;  /* Maybe lower if kernel optimized. */

void __udelay(unsigned long usecs)
{
	unsigned long long start = __vmgettime();
	unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;

	while ((__vmgettime() - start) < finish)
		cpu_relax(); /*  not sure how this improves readability  */
}
EXPORT_SYMBOL(__udelay);

Annotation

Implementation Notes