Ejemplo n.º 1
0
/*
 * Setup the local clock events for a CPU.
 */
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
	if (!twd_clk)
		twd_clk = twd_get_clock();

	if (!IS_ERR_OR_NULL(twd_clk))
		twd_timer_rate = clk_get_rate(twd_clk);
	else
		twd_calibrate_rate();

	clk->name = "local_timer";
	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
			CLOCK_EVT_FEAT_C3STOP;
	clk->rating = 350;
	clk->set_mode = twd_set_mode;
	clk->set_next_event = twd_set_next_event;

	__get_cpu_var(twd_ce) = clk;

	clockevents_config_and_register(clk, twd_timer_rate,
					0xf, 0xffffffff);

	/* Make sure our local interrupt controller has this enabled */
	gic_enable_ppi(clk->irq);
}
Ejemplo n.º 2
0
static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
	struct clock_event_device **this_cpu_clk;

	if (!twd_clk)
		twd_clk = twd_get_clock();

	if (!IS_ERR_OR_NULL(twd_clk))
		twd_timer_rate = clk_get_rate(twd_clk);
	else
		twd_calibrate_rate();

	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);

	clk->name = "local_timer";
	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
			CLOCK_EVT_FEAT_C3STOP;
	clk->rating = 350;
	clk->set_mode = twd_set_mode;
	clk->set_next_event = twd_set_next_event;
	clk->irq = twd_ppi;

	this_cpu_clk = __this_cpu_ptr(twd_evt);
	*this_cpu_clk = clk;

	clockevents_config_and_register(clk, twd_timer_rate,
					0xf, 0xffffffff);
	enable_percpu_irq(clk->irq, 0);

	return 0;
}
static int __init twd_local_timer_common_register(struct device_node *np)
{
    int err;

    twd_evt = alloc_percpu(struct clock_event_device *);
    if (!twd_evt) {
        err = -ENOMEM;
        goto out_free;
    }

    err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt);
    if (err) {
        pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err);
        goto out_free;
    }

    err = local_timer_register(&twd_lt_ops);
    if (err)
        goto out_irq;

    twd_get_clock(np);

    return 0;

out_irq:
    free_percpu_irq(twd_ppi, twd_evt);
out_free:
    iounmap(twd_base);
    twd_base = NULL;
    free_percpu(twd_evt);

    return err;
}
Ejemplo n.º 4
0
static unsigned long get_smp_twd_rate(void)
{
    if(IS_ERR_OR_NULL(twd_clk))
        twd_clk=twd_get_clock();
    BUG_ON(IS_ERR_OR_NULL(twd_clk));
    return clk_get_rate(twd_clk);
}
Ejemplo n.º 5
0
static int __init twd_local_timer_common_register(struct device_node *np)
{
	int err;

	twd_evt = alloc_percpu(struct clock_event_device);
	if (!twd_evt) {
		err = -ENOMEM;
		goto out_free;
	}

	err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt);
	if (err) {
		pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err);
		goto out_free;
	}

	err = register_cpu_notifier(&twd_timer_cpu_nb);
	if (err)
		goto out_irq;

#ifndef CONFIG_ARCH_CNS3XXX
	twd_get_clock(np);
#endif

	/*
	 * Immediately configure the timer on the boot CPU, unless we need
	 * jiffies to be incrementing to calibrate the rate in which case
	 * setup the timer in late_time_init.
	 */
	if (twd_timer_rate)
		twd_timer_setup();
	else
		late_time_init = twd_timer_setup;

	return 0;

out_irq:
	free_percpu_irq(twd_ppi, twd_evt);
out_free:
	iounmap(twd_base);
	twd_base = NULL;
	free_percpu(twd_evt);

	return err;
}
Ejemplo n.º 6
0
static void __cpuinit gt_setup(unsigned long base_paddr, unsigned bits)
{
	if ((read_cpuid_id() & 0xf00000) == 0)
		return;

	twd_clk = twd_get_clock();

	if (!IS_ERR_OR_NULL(twd_clk))
		twd_timer_rate = clk_get_rate(twd_clk);
	else
		twd_calibrate_rate();

	common_setup_called = true;
	
	gt_base = ioremap(base_paddr, SZ_256);
	BUG_ON(!gt_base);

	/* Start global timer */
	__raw_writel(1, gt_base + 0x8);

	tsc_info.type = IPIPE_TSC_TYPE_FREERUNNING;
	tsc_info.freq = twd_timer_rate;
	tsc_info.counter_vaddr = (unsigned long)gt_base;
	tsc_info.u.counter_paddr = base_paddr;
	
	switch(bits) {
	case 64:
		tsc_info.u.mask = 0xffffffffffffffffULL;
		break;
	case 32:
		tsc_info.u.mask = 0xffffffff;
		break;
	default:
		/* Only supported as a 32 bits or 64 bits */
		BUG();
	}

	__ipipe_tsc_register(&tsc_info);
}
Ejemplo n.º 7
0
/*
 * Setup the local clock events for a CPU.
 */
static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
	struct clock_event_device **this_cpu_clk;
	int cpu = smp_processor_id();

	/*
	 * If the basic setup for this CPU has been done before don't
	 * bother with the below.
	 */
	if (per_cpu(percpu_setup_called, cpu)) {
		__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
		clockevents_register_device(*__this_cpu_ptr(twd_evt));
		enable_percpu_irq(clk->irq, 0);
		return 0;
	}
	per_cpu(percpu_setup_called, cpu) = true;

	/*
	 * This stuff only need to be done once for the entire TWD cluster
	 * during the runtime of the system.
	 */
	if (!common_setup_called) {
		twd_clk = twd_get_clock();

		/*
		 * We use IS_ERR_OR_NULL() here, because if the clock stubs
		 * are active we will get a valid clk reference which is
		 * however NULL and will return the rate 0. In that case we
		 * need to calibrate the rate instead.
		 */
		if (!IS_ERR_OR_NULL(twd_clk))
			twd_timer_rate = clk_get_rate(twd_clk);
		else
			twd_calibrate_rate();

		common_setup_called = true;
	}

	/*
	 * The following is done once per CPU the first time .setup() is
	 * called.
	 */
	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);

	clk->name = "local_timer";
	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
			CLOCK_EVT_FEAT_C3STOP;
	clk->rating = 350;
	clk->set_mode = twd_set_mode;
	clk->set_next_event = twd_set_next_event;
	clk->irq = twd_ppi;

#if defined(CONFIG_IPIPE) && defined(CONFIG_SMP)
	printk(KERN_INFO "I-pipe, %lu.%03lu MHz timer\n",
	       twd_timer_rate / 1000000,
	       (twd_timer_rate % 1000000) / 1000);
	clk->ipipe_timer = __this_cpu_ptr(&twd_itimer);
	clk->ipipe_timer->irq = clk->irq;
	clk->ipipe_timer->ack = twd_ack;
	clk->ipipe_timer->min_delay_ticks = 0xf;
#endif

	this_cpu_clk = __this_cpu_ptr(twd_evt);
	*this_cpu_clk = clk;

	clockevents_config_and_register(clk, twd_timer_rate,
					0xf, 0xffffffff);
	enable_percpu_irq(clk->irq, 0);

	return 0;
}