static int ingenic_tcu_setup_cevt()

in ingenic-timer.c [141:202]


static int ingenic_tcu_setup_cevt(unsigned int cpu)
{
	struct ingenic_tcu *tcu = ingenic_tcu;
	struct ingenic_tcu_timer *timer = &tcu->timers[cpu];
	unsigned int timer_virq;
	struct irq_domain *domain;
	unsigned long rate;
	int err;

	timer->clk = ingenic_tcu_get_clock(tcu->np, timer->channel);
	if (IS_ERR(timer->clk))
		return PTR_ERR(timer->clk);

	err = clk_prepare_enable(timer->clk);
	if (err)
		goto err_clk_put;

	rate = clk_get_rate(timer->clk);
	if (!rate) {
		err = -EINVAL;
		goto err_clk_disable;
	}

	domain = irq_find_host(tcu->np);
	if (!domain) {
		err = -ENODEV;
		goto err_clk_disable;
	}

	timer_virq = irq_create_mapping(domain, timer->channel);
	if (!timer_virq) {
		err = -EINVAL;
		goto err_clk_disable;
	}

	snprintf(timer->name, sizeof(timer->name), "TCU%u", timer->channel);

	err = request_irq(timer_virq, ingenic_tcu_cevt_cb, IRQF_TIMER,
			  timer->name, timer);
	if (err)
		goto err_irq_dispose_mapping;

	timer->cpu = smp_processor_id();
	timer->cevt.cpumask = cpumask_of(smp_processor_id());
	timer->cevt.features = CLOCK_EVT_FEAT_ONESHOT;
	timer->cevt.name = timer->name;
	timer->cevt.rating = 200;
	timer->cevt.set_state_shutdown = ingenic_tcu_cevt_set_state_shutdown;
	timer->cevt.set_next_event = ingenic_tcu_cevt_set_next;

	clockevents_config_and_register(&timer->cevt, rate, 10, 0xffff);

	return 0;

err_irq_dispose_mapping:
	irq_dispose_mapping(timer_virq);
err_clk_disable:
	clk_disable_unprepare(timer->clk);
err_clk_put:
	clk_put(timer->clk);
	return err;
}