示例#1
0
void __init  atmel_time_init (void)
{
        register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE);
        register volatile struct at91_timer_channel* tc = &tt->chans[KERNEL_TIMER].ch;
        unsigned long v;

	/* enable Kernel timer */
	HW_AT91_TIMER_INIT(KERNEL_TIMER)

        /* No SYNC */
        tt->bcr = 0;
        /* program NO signal on XC1 */
        v = tt->bmr;
	v &= ~TCNXCNS(KERNEL_TIMER,3);
	v |= TCNXCNS(KERNEL_TIMER,1);
        tt->bmr = v;

        tc->ccr = 2;  /* disable the channel */

        /* select ACLK/128 as inupt frequency for TC1 and enable CPCTRG */
        tc->cmr = 3 | (1 << 14);

        tc->idr = ~0ul;  /* disable all interrupt */
        tc->rc = ((ARM_CLK/128)/HZ - 1);   /* load the count limit into the CR register */
        tc->ier = TC_CPCS;  /* enable CPCS interrupt */

	/*
	 * @todo do those really need to be function pointers ?
	 */
        gettimeoffset = atmel_gettimeoffset;
        atmel_timer_irq.handler = atmel_timer_interrupt;

	/* set up the interrupt */
        setup_irq(KERNEL_TIMER_IRQ_NUM, &atmel_timer_irq);

        /* enable the channel */
        tc->ccr = TC_SWTRG|TC_CLKEN;
}
示例#2
0
void at91_ipipe_init(struct clock_event_device *host_timer)
{
	unsigned char tc_divisors[] = { 2, 8, 32, 128, 0, };
	unsigned master_freq, divisor = 0, divided_freq = 0;
	unsigned long long wrap_ns;
	int tc_timer_clock;
	unsigned short v;
	struct clk *clk;

#ifdef CONFIG_ARCH_AT91SAM9263
	clk = clk_get(NULL, "tcb_clk");
#elif defined(CONFIG_ARCH_AT91SAM9G45)
	clk = clk_get(NULL, "tcb0_clk");
#else /* not AT91SAM9263 or AT91SAM9G45*/
	clk = clk_get(NULL, "tc"__stringify(CONFIG_IPIPE_AT91_TC) "_clk");
#endif

	clk_enable(clk);

	/* Disable the channel */
	at91_tc_write(AT91_TC_CCR, AT91_TC_CLKDIS);

	/* Disable all interrupts. */
	at91_tc_write(AT91_TC_IDR, ~0ul);

	master_freq = clk_get_rate(clk_get(NULL, "mck"));
	/* Find the first frequency above 1 MHz */
	for (tc_timer_clock = ARRAY_SIZE(tc_divisors) - 1;
	     tc_timer_clock >= 0; tc_timer_clock--) {
		divisor = tc_divisors[tc_timer_clock];
		divided_freq = (divisor
				? master_freq / divisor : AT91_SLOW_CLOCK);
		if (divided_freq > 1000000)
			break;
	}

	wrap_ns = (unsigned long long) (AT91_TC_REG_MASK + 1) * NSEC_PER_SEC;
	do_div(wrap_ns, divided_freq);

	if (divided_freq < 1000000)
		printk(KERN_INFO "AT91 I-pipe warning: could not find a"
		       " frequency greater than 1MHz\n");

	printk(KERN_INFO "AT91 I-pipe timer: div: %u, freq: %u.%06u MHz, wrap: "
	       "%u.%06u ms\n", divisor,
	       divided_freq / 1000000, divided_freq % 1000000,
	       (unsigned) wrap_ns / 1000000, (unsigned) wrap_ns % 1000000);

	/* Add a 1ms margin. It means that when an interrupt occurs, update_tsc
	   must be called within 1ms. update_tsc is called by acktimer when no
	   higher domain handles the timer, and called through set_dec when a
	   higher domain handles the timer. */
	wrap_ns -= 1000000;
	/* Set up the interrupt. */

	if (host_timer && host_timer->features & CLOCK_EVT_FEAT_ONESHOT
	    && host_timer->max_delta_ns > wrap_ns)
		host_timer->max_delta_ns = wrap_ns;

	/* No Sync. */
	at91_tc_write(AT91_TC_BCR, 0);

	/* program NO signal on XCN */
	v = readl((void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR));
	v &= ~TCNXCNS(CONFIG_IPIPE_AT91_TC, 3);
	v |= TCNXCNS(CONFIG_IPIPE_AT91_TC, 1); /* AT91_TC_TCNXCNS_NONE */
	writel(v, (void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR));

	/* Use the clock selected as input clock. */
	at91_tc_write(AT91_TC_CMR, tc_timer_clock);

	/* Load the TC register C. */
	write_RC(0xffff);

	/* Enable the channel. */
	at91_tc_write(AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG);

	at91_itimer.freq = divided_freq;
	at91_itimer.min_delay_ticks = ipipe_timer_ns2ticks(&at91_itimer, 2000);
	max_delta_ticks = ipipe_timer_ns2ticks(&at91_itimer, wrap_ns);
	ipipe_timer_register(&at91_itimer);

	tsc_info.freq = divided_freq;
	__ipipe_tsc_register(&tsc_info);

	at91_pic_muter_register();
}