static void nmdk_timer_delay_loop(unsigned long loops)
{
	unsigned long bclock, now;

	bclock = ~readl(mtu_base + MTU_VAL(0));
	do {
		now = ~readl(mtu_base + MTU_VAL(0));
		/* If timer have been cleared (suspend) or wrapped we exit */
		if (unlikely(now < bclock))
			return;
	} while ((now - bclock) < loops);
}
示例#2
0
static u32 notrace nomadik_read_sched_clock(void)
{
	if (unlikely(!mtu_base))
		return 0;

	return -readl(mtu_base + MTU_VAL(0));
}
示例#3
0
void __init nmdk_timer_init(void __iomem *base, int irq)
{
	unsigned long rate;
	struct clk *clk0, *pclk0;

	mtu_base = base;

	pclk0 = clk_get_sys("mtu0", "apb_pclk");
	BUG_ON(IS_ERR(pclk0));
	BUG_ON(clk_prepare(pclk0) < 0);
	BUG_ON(clk_enable(pclk0) < 0);

	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));
	BUG_ON(clk_prepare(clk0) < 0);
	BUG_ON(clk_enable(clk0) < 0);

	/*
	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
	 * for ux500.
	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
	 * with 16 gives too low timer resolution.
	 */
	rate = clk_get_rate(clk0);
	if (rate > 32000000) {
		rate /= 16;
		clk_prescale = MTU_CRn_PRESCALE_16;
	} else {
		clk_prescale = MTU_CRn_PRESCALE_1;
	}

	/* Cycles for periodic mode */
	nmdk_cycle = DIV_ROUND_CLOSEST(rate, HZ);


	/* Timer 0 is the free running clocksource */
	nmdk_clksrc_reset();

	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
			rate, 200, 32, clocksource_mmio_readl_down))
		pr_err("timer: failed to initialize clock source %s\n",
		       "mtu_0");

#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
#endif

	/* Timer 1 is used for events, register irq and clockevents */
	setup_irq(irq, &nmdk_timer_irq);
	nmdk_clkevt.cpumask = cpumask_of(0);
	nmdk_clkevt.irq = irq;
	clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);

	mtu_delay_timer.read_current_timer = &nmdk_timer_read_current_timer;
	mtu_delay_timer.freq = rate;
	register_current_timer_delay(&mtu_delay_timer);
}
示例#4
0
/* Used to calibrate the delay */
int read_current_timer(unsigned long *timer_val)
{
	if (prcmu_is_ulppll_disabled())
		return -EINVAL;

	*timer_val = ~readl(mtu_base + MTU_VAL(0));
	return 0;
}
示例#5
0
文件: timer.c 项目: CSCLOG/beaglebone
void __init nmdk_timer_init(void)
{
	unsigned long rate;
	struct clk *clk0;
	u32 cr = MTU_CRn_32BITS;

	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));

	clk_enable(clk0);

	/*
	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
	 * for ux500.
	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
	 * with 16 gives too low timer resolution.
	 */
	rate = clk_get_rate(clk0);
	if (rate > 32000000) {
		rate /= 16;
		cr |= MTU_CRn_PRESCALE_16;
	} else {
		cr |= MTU_CRn_PRESCALE_1;
	}

	/* Timer 0 is the free running clocksource */
	writel(cr, mtu_base + MTU_CR(0));
	writel(0, mtu_base + MTU_LR(0));
	writel(0, mtu_base + MTU_BGLR(0));
	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));

	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
			rate, 200, 32, clocksource_mmio_readl_down))
		pr_err("timer: failed to initialize clock source %s\n",
		       "mtu_0");

	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);

	/* Timer 1 is used for events */

	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);

	writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */

	nmdk_clkevt.max_delta_ns =
		clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
	nmdk_clkevt.min_delta_ns =
		clockevent_delta2ns(0x00000002, &nmdk_clkevt);
	nmdk_clkevt.cpumask	= cpumask_of(0);

	/* Register irq and clockevents */
	setup_irq(IRQ_MTU0, &nmdk_timer_irq);
	clockevents_register_device(&nmdk_clkevt);
}
unsigned long long sched_clock(void)
{
	unsigned long long v;

	if (unlikely(!mtu0_base))
		return 0;

	v = cnt32_to_63(0xffffffff - readl(mtu0_base + MTU_VAL(1)));
	return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
}
示例#7
0
文件: timer.c 项目: CSCLOG/beaglebone
unsigned long long notrace sched_clock(void)
{
	u32 cyc;

	if (unlikely(!mtu_base))
		return 0;

	cyc = -readl(mtu_base + MTU_VAL(0));
	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
}
void __init nmdk_timer_init(void)
{
	unsigned long rate;
	struct clk *clk0;
	int ret;

	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));

	ret = clk_prepare_enable(clk0);
	BUG_ON(ret != 0);

	/*
	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
	 * for ux500.
	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
	 * with 16 gives too low timer resolution.
	 */
	rate = clk_get_rate(clk0);
	if (rate > 32000000) {
		rate /= 16;
		clk_prescale = MTU_CRn_PRESCALE_16;
	} else {
		clk_prescale = MTU_CRn_PRESCALE_1;
	}

	nmdk_cycle = (rate + HZ/2) / HZ;


	/* Timer 0 is the free running clocksource */
	nmdk_clksrc_reset();

	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
			rate, 200, 32, clocksource_mmio_readl_down))
		pr_err("timer: failed to initialize clock source %s\n",
		       "mtu_0");

#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
#endif

	/* Timer 1 is used for events, register irq and clockevents */
	setup_irq(IRQ_MTU0, &nmdk_timer_irq);
	nmdk_clkevt.cpumask = cpumask_of(0);
	clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);
#ifdef ARCH_HAS_READ_CURRENT_TIMER
	set_delay_fn(nmdk_timer_delay_loop);
#endif

}
示例#9
0
void __init nmdk_timer_init(void __iomem *base)
{
	unsigned long rate;
	struct clk *clk0;

	mtu_base = base;
	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));
	BUG_ON(clk_prepare(clk0) < 0);
	BUG_ON(clk_enable(clk0) < 0);

	rate = clk_get_rate(clk0);
	if (rate > 32000000) {
		rate /= 16;
		clk_prescale = MTU_CRn_PRESCALE_16;
	} else {
		clk_prescale = MTU_CRn_PRESCALE_1;
	}

	nmdk_cycle = (rate + HZ/2) / HZ;


	
	nmdk_clksrc_reset();

	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
			rate, 200, 32, clocksource_mmio_readl_down))
		pr_err("timer: failed to initialize clock source %s\n",
		       "mtu_0");

#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
#endif

	
	setup_irq(IRQ_MTU0, &nmdk_timer_irq);
	nmdk_clkevt.cpumask = cpumask_of(0);
	clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);
}
/*
 * clocksource: the MTU device is a decrementing counters, so we negate
 * the value being read.
 */
static cycle_t u8500_read_timer(struct clocksource *cs)
{
	u32 count = readl(mtu0_base + MTU_VAL(1));
	return ~count;
}
示例#11
0
static unsigned long nmdk_timer_read_current_timer(void)
{
	return ~readl_relaxed(mtu_base + MTU_VAL(0));
}
示例#12
0
文件: timer.c 项目: CSCLOG/beaglebone
static void notrace nomadik_update_sched_clock(void)
{
	u32 cyc = -readl(mtu_base + MTU_VAL(0));
	update_sched_clock(&cd, cyc, (u32)~0);
}
/* Used to calibrate the delay */
int read_current_timer(unsigned long *timer_val)
{
	*timer_val = ~readl(mtu_base + MTU_VAL(0));
	return 0;
}
示例#14
0
/* clocksource: MTU decrements, so we negate the value being read. */
static cycle_t nmdk_read_timer(struct clocksource *cs)
{
	return -readl(mtu_base + MTU_VAL(0));
}
示例#15
0
void __init nmdk_timer_init(void)
{
	unsigned long rate;
	struct clk *clk0;
	unsigned long min_delta_ticks;

	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));

	clk_enable(clk0);

	/*
	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
	 * for ux500.
	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
	 * with 16 gives too low timer resolution.
	 */
	rate = clk_get_rate(clk0);
	if (rate > 32000000) {
		rate /= 16;
		clk_prescale = MTU_CRn_PRESCALE_16;
	} else {
		clk_prescale = MTU_CRn_PRESCALE_1;
	}

	nmdk_cycle = (rate + HZ/2) / HZ;


	/* Timer 0 is the free running clocksource */
	nmdk_clksrc_reset();

	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
			rate, 200, 32, clocksource_mmio_readl_down))
		pr_err("timer: failed to initialize clock source %s\n",
		       "mtu_0");

#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
#endif

	/* Timer 1 is used for events */

	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);

	nmdk_clkevt.max_delta_ns =
		clockevent_delta2ns(0xffffffff, &nmdk_clkevt);

	/* When ulppll is disabled timer is working on 32kHz clock. */
	min_delta_ticks = prcmu_is_ulppll_disabled()? 0x5 : 0x2;
	nmdk_clkevt.min_delta_ns =
		clockevent_delta2ns(min_delta_ticks, &nmdk_clkevt);
	nmdk_clkevt.cpumask	= cpumask_of(0);

	/* Register irq and clockevents */
	setup_irq(IRQ_MTU0, &nmdk_timer_irq);
	clockevents_register_device(&nmdk_clkevt);
#ifdef ARCH_HAS_READ_CURRENT_TIMER
	if (!prcmu_is_ulppll_disabled())
		set_delay_fn(nmdk_timer_delay_loop);
#endif

}