Beispiel #1
0
/*
 * Setup the local clock events for a CPU.
 */
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
	unsigned int cpu = smp_processor_id();
	struct kona_td kona_td;
	struct timer_ch_cfg config;

	/* allocate an AON timer channel as local tick timer
	 */
	kona_td = (struct kona_td)__get_cpu_var(percpu_kona_td);

	if (!kona_td.allocated) {
		kona_td.kona_timer =
		    kona_timer_request(TICK_TIMER_NAME,
				       TICK_TIMER_OFFSET + cpu);
		if (kona_td.kona_timer) {
			kona_td.allocated = true;
		} else {
			pr_err("%s: Failed to allocate %s channel %d as"
			       "CPU %d local tick device\n", __func__,
			       TICK_TIMER_NAME,
			       TICK_TIMER_OFFSET + cpu, cpu);
			return -ENXIO;
		}
	}

	/*
	 * In the future: The following codes should be one time configuration
	 */
	config.mode = MODE_ONESHOT;
	config.arg = evt;
	config.cb = kona_tick_interrupt_cb;
	kona_timer_config(kona_td.kona_timer, &config);

	irq_set_affinity(kona_td.kona_timer->irq, cpumask_of(cpu));

	evt->name = "local_timer";
	evt->cpumask = cpumask_of(cpu);
	evt->irq = kona_td.kona_timer->irq;
	evt->set_next_event = kona_tick_set_next_event;
	evt->set_mode = kona_tick_set_mode;
	evt->features = CLOCK_EVT_FEAT_ONESHOT;
	evt->rating = 250;
	evt->shift = 32;
	evt->mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, evt->shift);
	evt->max_delta_ns = clockevent_delta2ns(MAX_KONA_COUNT_CLOCK, evt);
	/* There is MIN_KONA_DELTA_CLOCK clock cycles delay in HUB Timer by
	 * ASIC limitation. When min_delta_ns set N, real requested load value
	 * in hrtimer becomes N - 1. So add 1 to be MIN_DELTA_CLOCK
	 */
	evt->min_delta_ns = clockevent_delta2ns(MIN_KONA_DELTA_CLOCK + 1, evt);

	per_cpu(percpu_kona_td, cpu) = kona_td;

	clockevents_register_device(evt);

	return 0;
}
static void __init timers_init(struct gp_timer_setup *gpt_setup)
{
	struct timer_ch_cfg evt_tm_cfg;

	if (kona_timer_modules_init() < 0) {
		pr_err
		    ("timers_init: Unable to initialize kona timer modules \r\n");
		return;
	}

	if (kona_timer_module_set_rate(gpt_setup->name, gpt_setup->rate) < 0) {
		pr_err("timers_init: Unable to set the clock rate to %d	\r\n",
		       gpt_setup->rate);
		return;
	}

	/* Initialize Event timer */
	gpt_evt = kona_timer_request(gpt_setup->name, gpt_setup->ch_num);
	if (gpt_evt == NULL) {
		pr_err("timers_init: Unable to get GPT timer for event\r\n");
		return;
	}

	pr_info("timers_init: === SYSTEM TIMER NAME: %s CHANNEL NUMBER %d \
	RATE %d \r\n", gpt_setup->name, gpt_setup->ch_num, gpt_setup->rate);

	evt_tm_cfg.mode = MODE_ONESHOT;
	evt_tm_cfg.arg = &clockevent_gptimer;
	evt_tm_cfg.cb = gptimer_interrupt_cb;

	kona_timer_config(gpt_evt, &evt_tm_cfg);

	gptimer_set_next_event((CLOCK_TICK_RATE / HZ), NULL);

	/*
	 * IMPORTANT
	 * Note that we don't want to waste a channel for clock source. In Kona
	 *timer module by default there is a counter that keeps counting
	 *irrespective of the channels. So instead of implementing a periodic
	 *timer using a channel (which in the HW is not peridoic) we can
	 *simply read the counters of the timer that is used for event and
	 *send it for source. The only catch is that this timer should not be
	 *stopped by PM or any other sub-systems.
	 */
	gpt_src = gpt_evt;

	return;
}
Beispiel #3
0
static ssize_t
kona_timer_start_test(struct device *dev, struct device_attribute *attr,
	  const char *buf, size_t n)
{
	unsigned int ch_num, mode, count;
	char name[255];

	if (sscanf(buf, "%s %d %d %d", name, &ch_num, &mode, &count) == 4) {
		pr_info("channel_num:%d mode(0-periodic 1-oneshot):%d "
			"count:%d\n", ch_num, mode, count);

		if (kt == NULL)
			kt = kona_timer_request(name, ch_num);

		if (kt == NULL) {
			pr_err("kona_timer_request returned error\n");
			goto out;
		}

		cfg.mode = mode;
		cfg.arg  = kt;
		cfg.cb	 = timer_callback;
		cfg.reload = count;

		if (kona_timer_config(kt, &cfg) < 0) {
			pr_err("kona_timer_config returned error\n");
			goto out;
		}

		if (kona_timer_set_match_start(kt, count) < 0) {
			pr_err("kona_timer_set_match_start returned error\n");
			goto out;
		}
		pr_info("Timer test started\n");
out:
		return n;
	}

	pr_info("\nusage: echo [name (aon-timer/slave-timer)] "
		"[channel num (0-3)] [mode(0-periodic"
		"1-oneshot)] [count value] > /sys/bcm/timer_start_test\n");
	return -EINVAL;
}
Beispiel #4
0
static int kona_timer_unit_test_run(const char *clk_name,
				     unsigned long clk_rate)
{
	struct kona_timer *lkt;
	int i;
	unsigned long flags;
	unsigned long req_cycle;

	pr_info("%s started!\n", __func__);

	lkt = kona_timer_request((char *)clk_name, -1);
	if (lkt == NULL) {
		pr_err("kona_timer_request returned error\n");
		return -EINVAL;
	}
	pr_info("%s ch_num: %d acquired!\n", clk_name, lkt->ch_num);

	timer_m = (struct timer_measure *)
			kmalloc(sizeof(struct timer_measure), GFP_KERNEL);

	if (!timer_m) {
		pr_err("%s memory allocation failed!\n", __func__);
		return -EINVAL;
	}

	spin_lock_init(&timer_m->lock);

#ifdef CONFIG_PREEMPT
	/* Ensure that cond_resched() won't try to preempt anybody */
	add_preempt_count(PREEMPT_ACTIVE);
#endif

	/*----------------------------------------------------------------------
	 * Test 1 : 1 clock cycle test
	 *  - set up 1 clock cycle timer request and measure the expiration
	 *    time.
	 */
	msleep(50);
	pr_info("=== Test case 1 ===\n");
	pr_info("1 clock tick one shot for 1 ms\n");

	req_cycle = 1;
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	timer_m->start[timer_m->counter] = (u64)kona_timer_get_counter(lkt);
	timer_m->req_cycle[timer_m->counter] = req_cycle;
	spin_unlock_irqrestore(&timer_m->lock, flags);

	kona_timer_unit_test_program(lkt, MODE_ONESHOT, req_cycle);

	mdelay(1);
	kona_timer_stop(lkt);

	/* Error check */
	print_unit_test_result(atomic_read(&timer_exp_count), 1, clk_rate);

	if (atomic_read(&timer_exp_count) != 1)
		goto error;

	/*----------------------------------------------------------------------
	 * Test 2 : peridic 1 clock timer test
	 *  - set up periodic 1 clock cycle timer request. SW will handle
	 *    periodic timer on every timer expiration. Wait for certain time
	 *    and check how many timers were expired and mesaure the time.
	 */
	msleep(50);
	pr_info("=== Test case 2 ===\n");
	pr_info("Periodic 1 clock tick for 1 ms\n");

	req_cycle = 1;
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	timer_m->start[timer_m->counter] = (u64)kona_timer_get_counter(lkt);

	for (i = 0; i < TIMER_MEASURE_MAX; i++)
		timer_m->req_cycle[i] = req_cycle;
	spin_unlock_irqrestore(&timer_m->lock, flags);

	kona_timer_unit_test_program(lkt, MODE_PERIODIC, req_cycle);

	/* mdelay() may be delayed by busy timer request. Should be short */
	mdelay(1);
	kona_timer_stop(lkt);
	pr_info("Total expiration count: %d\n", atomic_read(&timer_exp_count));
	print_unit_test_result(atomic_read(&timer_exp_count),
			       atomic_read(&timer_exp_count), clk_rate);

	/*----------------------------------------------------------------------
	* Test 3 : one-shot timer test with various time values
	*  - test various short clock cycles and check
	*    timer expiration and real run time of timer.
	*/
	msleep(50);
	pr_info("=== Test case 3 ===\n");
	pr_info("0~20 clock tick test for 1s, 50ms delay between each req\n");
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	spin_unlock_irqrestore(&timer_m->lock, flags);

	for (i = 0; i < 20; i++) {
		spin_lock_irqsave(&timer_m->lock, flags);
		timer_m->busy = 1;
		timer_m->counter = i;
		timer_m->start[i] =
			(u64)kona_timer_get_counter(lkt);
		timer_m->req_cycle[i] = i;
		kona_timer_unit_test_program(lkt, MODE_ONESHOT, i);
		timer_m->busy = 0;
		spin_unlock_irqrestore(&timer_m->lock, flags);

		mdelay(50);
		kona_timer_stop(lkt);
	}

	print_unit_test_result(atomic_read(&timer_exp_count), 20, clk_rate);

	if (atomic_read(&timer_exp_count) != 20)
		goto error;

	/*----------------------------------------------------------------------
	* Test 4 : one-shot timer test with various time values and delays.
	*  - test various short clock cycles with various short delays.
	*    Verify the timer expiration and timer run-time.
	*/
	msleep(50);
	pr_info("=== Test case 4 ===\n");
	pr_info("0~29 cycle timer test, 0~29 + 3 clock cycle wait\n");
	pr_info("   Ex)1 clock : wait for 4 clock cycle time\n");
	pr_info("   Ex)10 clock : wait for 13 clock cycle time\n");
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	spin_unlock_irqrestore(&timer_m->lock, flags);

	for (i = 0; i < 30; i++) {
		spin_lock_irqsave(&timer_m->lock, flags);
		timer_m->busy = 1;
		timer_m->counter = i;
		timer_m->start[i] =
			(u64)kona_timer_get_counter(lkt);
		timer_m->req_cycle[i] = i;
		kona_timer_unit_test_program(lkt, MODE_ONESHOT, i);
		timer_m->busy = 0;
		spin_unlock_irqrestore(&timer_m->lock, flags);

		kona_clock_delay(lkt, i + 3);
	}
	kona_timer_stop(lkt);
	pr_info("Total expiration count: %d\n", atomic_read(&timer_exp_count));
	print_unit_test_result(atomic_read(&timer_exp_count), 30, clk_rate);

	/*----------------------------------------------------------------------
	 * Test 5 : one-shot timer test with short-long time/delay.
	 *  - test various short/long clock cycles with various short/long
	 *    delays. Verify the timer expiration and timer run-time.
	 */
	msleep(50);
	pr_info("=== Test case 5 ===\n");
	pr_info("short and long timer test\n");
	pr_info("   short delay: 0~19 clock cycle wait\n");
	pr_info("   long  delay: 50 ms wait\n");
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	spin_unlock_irqrestore(&timer_m->lock, flags);

	for (i = 0; i < 20; i++) {
		/* Short timer request */
		spin_lock_irqsave(&timer_m->lock, flags);
		timer_m->busy = 1;
		timer_m->counter = 2 * i;
		timer_m->start[2 * i] =
			(u64)kona_timer_get_counter(lkt);
		timer_m->req_cycle[2 * i] = i;
		kona_timer_unit_test_program(lkt, MODE_ONESHOT, i);
		timer_m->busy = 0;
		spin_unlock_irqrestore(&timer_m->lock, flags);

		kona_clock_delay(lkt, i + 1);

		/* Long timer request */
		req_cycle = clk_rate / 50; /* 20ms */
		spin_lock_irqsave(&timer_m->lock, flags);
		timer_m->busy = 1;
		timer_m->counter = 2 * i + 1;
		timer_m->start[2 * i + 1] =
			(u64)kona_timer_get_counter(lkt);
		timer_m->req_cycle[2 * i + 1] = req_cycle;
		kona_timer_unit_test_program(lkt, MODE_ONESHOT, req_cycle);
		timer_m->busy = 0;
		spin_unlock_irqrestore(&timer_m->lock, flags);

		mdelay(1000/50 * 2); /* 40 ms */
	}
	kona_timer_stop(lkt);
	pr_info("Total expiration count: %d\n", atomic_read(&timer_exp_count));
	print_unit_test_result(atomic_read(&timer_exp_count), 20 * 2, clk_rate);

	/*----------------------------------------------------------------------
	 * Test 6 : periodic 1s timer test
	 *          wait for 10.5 sec with 1s periodic timer request
	 */
	msleep(50);
	pr_info("=== Test case 6 ===\n");
	pr_info("Periodic 1s timer test for 10.5s\n");

	req_cycle = clk_rate;
	atomic_set(&timer_exp_count, 0);

	spin_lock_irqsave(&timer_m->lock, flags);
	memset(timer_m, 0, sizeof(struct timer_measure));
	timer_m->start[timer_m->counter] = (u64)kona_timer_get_counter(lkt);

	for (i = 0; i < TIMER_MEASURE_MAX; i++)
		timer_m->req_cycle[i] = req_cycle;
	spin_unlock_irqrestore(&timer_m->lock, flags);

	kona_timer_unit_test_program(lkt, MODE_PERIODIC, clk_rate);

	msleep(10500);
	kona_timer_stop(lkt);

	print_unit_test_result(atomic_read(&timer_exp_count),
			       atomic_read(&timer_exp_count), clk_rate);

	if (atomic_read(&timer_exp_count) != 10)
		goto error;
	msleep(50);

	/*
	 * End of kona timer unit test
	 */

	kona_timer_free(lkt);

	pr_info("%s Passed!\n", __func__);

#ifdef CONFIG_PREEMPT
	sub_preempt_count(PREEMPT_ACTIVE);
#endif
	kfree(timer_m);
	timer_m = NULL;

	return 0;

error:
	kona_timer_stop(lkt);
	kona_timer_free(lkt);

	pr_err("%s Failed\n", __func__);

#ifdef CONFIG_PREEMPT
	sub_preempt_count(PREEMPT_ACTIVE);
#endif
	kfree(timer_m);
	timer_m = NULL;

	return -EINVAL;
}