void __init gic_clocksource_init(unsigned int frequency) { gic_frequency = frequency; gic_timer_irq = MIPS_GIC_IRQ_BASE + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); __gic_clocksource_init(); gic_clockevent_init(); /* And finally start the counter */ gic_start_count(); }
static void __init __gic_clocksource_init(void) { /* Set clocksource mask. */ gic_clocksource.mask = CLOCKSOURCE_MASK(gic_get_count_width()); /* Calculate a somewhat reasonable rating value. */ gic_clocksource.rating = 200 + gic_frequency / 10000000; clocksource_register_hz(&gic_clocksource, gic_frequency); gic_clockevent_init(); /* And finally start the counter */ gic_start_count(); }
void __init plat_time_init(void) { #if defined (CONFIG_CSRC_GIC) if (gic_present) { gic_clocksource_init(mips_cpu_feq); gic_start_count(); } else #endif mips_hpt_frequency = mips_cpu_feq / 2; #if defined (CONFIG_RALINK_SYSTICK_COUNTER) ra_systick_clockevent_init(); ra_systick_clocksource_init(); #endif }
static int __init gic_clocksource_of_init(struct device_node *node) { struct clk *clk; int ret; if (!gic_present || !node->parent || !of_device_is_compatible(node->parent, "mti,gic")) { pr_warn("No DT definition for the mips gic driver"); return -ENXIO; } clk = of_clk_get(node, 0); if (!IS_ERR(clk)) { if (clk_prepare_enable(clk) < 0) { pr_err("GIC failed to enable clock\n"); clk_put(clk); return PTR_ERR(clk); } gic_frequency = clk_get_rate(clk); } else if (of_property_read_u32(node, "clock-frequency", &gic_frequency)) { pr_err("GIC frequency not specified.\n"); return -EINVAL;; } gic_timer_irq = irq_of_parse_and_map(node, 0); if (!gic_timer_irq) { pr_err("GIC timer IRQ not specified.\n"); return -EINVAL;; } ret = __gic_clocksource_init(); if (ret) return ret; ret = gic_clockevent_init(); if (!ret && !IS_ERR(clk)) { if (clk_notifier_register(clk, &gic_clk_nb) < 0) pr_warn("GIC: Unable to register clock notifier\n"); } /* And finally start the counter */ gic_start_count(); return 0; }
/* * Estimate CPU and GIC frequencies. */ static void __init estimate_frequencies(void) { unsigned long flags; unsigned int count, start; cycle_t giccount = 0, gicstart = 0; #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000; return; #endif local_irq_save(flags); /* Start counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); /* Initialize counters. */ start = read_c0_count(); if (gic_present) { gic_start_count(); gicstart = gic_read_count(); } /* Read counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); count = read_c0_count(); if (gic_present) giccount = gic_read_count(); local_irq_restore(flags); count -= start; mips_hpt_frequency = count; if (gic_present) { giccount -= gicstart; gic_frequency = giccount; } }
/* * Estimate CPU and GIC frequencies. */ static void __init estimate_frequencies(void) { unsigned long flags; unsigned int count, start; unsigned char secs1, secs2, ctrl; int secs; u64 giccount = 0, gicstart = 0; #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000; return; #endif local_irq_save(flags); if (gic_present) gic_start_count(); /* * Read counters exactly on rising edge of update flag. * This helps get an accurate reading under virtualisation. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); start = read_c0_count(); if (gic_present) gicstart = gic_read_count(); /* Wait for falling edge before reading RTC. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); secs1 = CMOS_READ(RTC_SECONDS); /* Read counters again exactly on rising edge of update flag. */ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); count = read_c0_count(); if (gic_present) giccount = gic_read_count(); /* Wait for falling edge before reading RTC again. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); secs2 = CMOS_READ(RTC_SECONDS); ctrl = CMOS_READ(RTC_CONTROL); local_irq_restore(flags); if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { secs1 = bcd2bin(secs1); secs2 = bcd2bin(secs2); } secs = secs2 - secs1; if (secs < 1) secs += 60; count -= start; count /= secs; mips_hpt_frequency = count; if (gic_present) { giccount = div_u64(giccount - gicstart, secs); gic_frequency = giccount; } }