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 + -
显示快捷键?