time.c

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

C
234
字号
/*  * linux/arch/arm/mach-omap2/time.c *  * Support functions using 24xx GeneralPurposeTimers * Timers are up counters and overflow is not at 0xffffffff but * 1 clock cycle after 0xffffffff * Usage: * Timer2 - System or Heartbeat Timer * Timer3 - Time Stamp Counter * * Copyright (C) 2004 Texas Instruments, Inc.  * * Copied from: * arch/arm/mach-omap/time.c * Copyright (C) 2000 RidgeRun, 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/kernel.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/system.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/leds.h>#include <asm/irq.h>#include <asm/mach/irq.h>#include <asm/mach/time.h>#ifndef __instrument#define __instrument#define __noinstrument __attribute__ ((no_instrument_function))#endiftypedef 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 mputimer_addr(n) ((n>1) ? (OMAP24XX_TIMER3_BASE + (n-2)*OMAP24XX_GPTIMER_OFF): \	(OMAP24XX_TIMER1_BASE + (n)*OMAP24XX_GPTIMER_OFF))#define mputimer_base(n) (volatile mputimer_regs_t*)IO_ADDRESS(mputimer_addr(n))/* After programming PTV with 0, the timer count rate is 6 MHz. WARNING! this must be an even number, or machinecycles_to_usecs below will break.*/#define MPUTICKS_PER_USEC 6static int mputimer_started[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };static inline void __noinstrument timer_delay(void){	int i;	for (i = 0; i < 100000; i++) ;}/*we are not using the compare feature of 24xxTimer *overflow in 24xxTimer occurs 1 clock cycle after cuonter register reaching *0xffffffff  */static inline void __noinstrument start_mputimer(int n, unsigned long load_val){	volatile mputimer_regs_t *timer = mputimer_base(n);	mputimer_started[n] = 0;	timer->tldr = 0xffffffff - load_val;	timer->tsicr = 0x0;	timer_delay();	timer->tcrr = 0xffffffff - load_val;	timer_delay();	/*enable overflow interrupt */	timer->tier = ((0x1 << 1));	/*prescalar enable,auto reload mode,start timer */	timer->tclr = ((0x1 << 5) | (0x1 << 1) | (0x1 << 0));	mputimer_started[n] = 1;}static inline unsigned long __noinstrument read_mputimer(int n){	volatile mputimer_regs_t *timer = mputimer_base(n);	return (mputimer_started[n] ? timer->tcrr : 0);}void __noinstrument start_mputimer1(unsigned long load_val){	start_mputimer(0, load_val);}void __noinstrument start_mputimer2(unsigned long load_val){	start_mputimer(1, load_val);}void __noinstrument start_mputimer3(unsigned long load_val){	volatile mputimer_regs_t *timer = mputimer_base(2);	mputimer_started[2] = 0;	timer->tldr = 0xffffffff - load_val;	/*posted mode disabled */	timer->tsicr = 0x0;	timer_delay();	timer->tcrr = 0xffffffff - load_val;	timer_delay();	/* no interrupt generation */	timer->tier = 0x0;	/*prescalar enable,auto reload mode,start timer */	timer->tclr = ((0x1 << 5) | (0x1 << 1) | (0x1 << 0));	mputimer_started[2] = 1;}unsigned long __noinstrument read_mputimer1(void){	return read_mputimer(0);}unsigned long __noinstrument read_mputimer2(void){	return read_mputimer(1);}unsigned long __noinstrument read_mputimer3(void){	return read_mputimer(2);}unsigned long __noinstrument do_getmachinecycles(void){	return read_mputimer3();}unsigned long __noinstrument machinecycles_to_usecs(unsigned long mputicks){/* round up to nearest usec*/	return ((mputicks / (MPUTICKS_PER_USEC / 2)) + 1) >> 1;}/* * This holds the value in counter register of Timer3 * at the time of the last system timer interrupt */unsigned long systimer_mark;/*this function returns the time(in usec) elapsed *from the last System Timer interrupt */static unsigned long omap24xx_gettimeoffset(void){	/* return elapsed usecs since last system timer ISR */	return machinecycles_to_usecs(do_getmachinecycles() - systimer_mark);}/*System Timer Interupt Handler*/static irqreturn_t omap24xx_timer_interrupt(int irq,					    void *dev_id, struct pt_regs *regs){	unsigned long now, ilatency;	u32 temp;	volatile mputimer_regs_t *timer = mputimer_base(1);	/*	 * mark the time at which the timer interrupt ocurred using	 * timer3. We need to remove interrupt latency, which we can	 * retrieve from the current system timer2 counter. Both the	 * offset timer2 and the system timer3 are counting at 6MHz,	 * so we're ok.	 */	now = read_mputimer3();	ilatency =	    read_mputimer2() - (0xffffffff - MPUTICKS_PER_USEC * 1000 * 10);	systimer_mark = now - ilatency;	temp = timer->tisr;	/*clear timer interrupt status register */	timer->tisr = temp;	timer_tick(regs);	return IRQ_HANDLED;}static struct irqaction omap24xx_timer_irq = {	.name = "OMAP24xx Timer Tick",	.flags = SA_INTERRUPT,	.handler = omap24xx_timer_interrupt};void __init omap24xx_time_init(void){	gettimeoffset = omap24xx_gettimeoffset;	/*start Time Stamp Counter */	start_mputimer3(0xffffffff);	/* since we don't call request_irq, we must init the structure */	setup_irq(INT_GPT2_IRQ, &omap24xx_timer_irq);	/*start System or Heartbeat Timer 	 *interrupt frequency 10msecond	 */	start_mputimer2(MPUTICKS_PER_USEC * 1000 * 10 - 1);}

⌨️ 快捷键说明

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