hrtime.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 162 行

C
162
字号
/*  * linux/arch/arm/mach-omap2/hrtime.c *  * High-Res Timer Implementation for OMAP2 * HRT port on 24xx uses Timer4 to receive notification after elapsed time * * Copyright (C) 2004 Texas Instruments, Inc.  *  * This package is free software; you can redistribute it and/or modify  * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation.  *  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.  */#include <linux/config.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/time.h>#include <linux/hrtime.h>#include <linux/timex.h>#include <linux/kernel.h>#include <linux/interrupt.h>#include <asm/errno.h>#include <asm/hardware.h>#include <asm/mach/irq.h>#include <asm/irq.h>int hrtimer_use = 0;typedef struct {	u32 tidr;		/*timer identification */	u32 filer1;		/*reserved */	u32 filer2;		/*reserved */	u32 filer3;		/*reserved */	u32 ti_ocpcfg;		/*ocp configuration */	u32 tistat;		/*interrupt status */	u32 tisr;		/*Timer status */	u32 tier;		/*Timer interrupt enable */	u32 twer;		/*Timer wake-up enable */	u32 tclr;		/*Timer control */	u32 tcrr;		/*Timer counter */	u32 tldr;		/*Timer load */	u32 ttgr;		/*Timer trigger */	u32 twps;		/*Timer write posted status */	u32 tmar;		/*Timer match */	u32 tcar;		/*Timer capture */	u32 tsicr;		/*Timer synchronization interface control */} mputimer_regs_t;#define HRT_TIMER_BASE      IO_ADDRESS(OMAP24XX_TIMER4_BASE)#define HRT_TIMER_IRQ  INT_GPT4_IRQ/*Program HRT Timer to generate interrupt at (ref_jiffies *  *arch_cycles_per_jiffy)+ref_cycles clock cycles from current time *this is called by __run_timers.this means that some Kernel Timer in Kernel *Timer List will expire at (ref_jiffies * arch_cycles_per_jiffy) * +ref_cycles from current time */int schedule_hr_timer_int(unsigned ref_jiffies, int ref_cycles){	int temp_cycles;	volatile mputimer_regs_t *subhz_timer =	    (mputimer_regs_t *) HRT_TIMER_BASE;	BUG_ON(ref_cycles < 0);	/*calculate the time(in terms of clock cycles) the time interval 	   from now to the time specified by ref_jiffies+ref_cycles after 	   ref_jiffies	 */	temp_cycles = (ref_jiffies - jiffies) * arch_cycles_per_jiffy +	    ref_cycles - get_arch_cycles(jiffies);	if (unlikely(temp_cycles <= 0))		return -ETIME;	/*posted mode active */	subhz_timer->tsicr = 0x0;	subhz_timer->tcrr = 0xffffffff - (temp_cycles - 1);	/*enable overflow interrupt */	subhz_timer->tier = (0x1 << 1);	/*prescalar enable,start timer */	subhz_timer->tclr = ((0x1 << 5) | (0x1 << 0));	return 0;}/*get the elapsed timer(in terms of clock cycles) from ref_jiffies*/int get_arch_cycles(unsigned ref_jiffies){	extern unsigned long systimer_mark;	extern unsigned long do_getmachinecycles(void);	int ret;	unsigned temp_jiffies;	unsigned diff_jiffies;	do {		/* snapshot jiffies */		temp_jiffies = jiffies;		/*ensures that the opeartors placed before this are finished		 *before starting operations placed after this		 */		barrier();		/* calculate cycles since the current jiffy */		ret = do_getmachinecycles() - systimer_mark;		/* compensate for ref_jiffies in the past */		if (unlikely(diff_jiffies = jiffies - ref_jiffies))			ret += diff_jiffies * arch_cycles_per_jiffy;		barrier();		/* repeat if we didn't have a consistent view of the world */	} while (unlikely(temp_jiffies != jiffies));	return ret;}/*interrupt handler for HRT Timer*/static irqreturn_t hr_timer_interrupt(int irq, void *dev_id,				      struct pt_regs *regs){	volatile mputimer_regs_t *subhz_timer =	    (mputimer_regs_t *) HRT_TIMER_BASE;	/*clear timer interrupt status register */	subhz_timer->tisr = subhz_timer->tisr;	/*stop timer */	subhz_timer->tclr = 0;	/*some Kernel Timer would have expired this time	 *so process the timer list 	 *do_hr_timer_int define as run_local_timers in include/linux/hrtime.h	 *run_local_timers in turn calls __run_timers which process timer list	 */	do_hr_timer_int();	return IRQ_HANDLED;}static struct irqaction hr_timer_irq = {	.name = "high-res timer",	.handler = hr_timer_interrupt,	.flags = SA_INTERRUPT};static int hr_timer_init(void){	int ret;	volatile mputimer_regs_t *subhz_timer =	    (mputimer_regs_t *) HRT_TIMER_BASE;	subhz_timer->tclr = 0;	ret = setup_irq(HRT_TIMER_IRQ, &hr_timer_irq);	hrtimer_use = 1;	return ret;}__initcall(hr_timer_init);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?