⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tid_8xx_timer.c

📁 mpc8xx driver(led), based on tqm8
💻 C
字号:
/*********************************************************************** * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * Jean-Jacques Germond, Fr閐閞ic Soulier, Christian Batt; Alcatel * C/O jjg@sxb.bsf.alcatel.fr * * All rights reserved. * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU *Library* General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * *Library* General Public License for more details. * * You should have received a copy of the GNU *Library* General Public * License along with this program (see file COPYING.LIB); if not, * write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. * ***********************************************************************//* See AR pg:21  */#define __NO_VERSION__#include "tid_def.h"		/* for generic timer definitions*/#include <asm/init.h>		/* for __initfunc		*/#include <asm/8xx_immap.h>	/* for IMMR   definitions	*/#include <asm/mpc8xx.h>		/* for MPC8xx definitions	*/#include "commproc.h"		/* for CPM Int. Vector defs	*/#include "tid_8xx_def.h"	/* for MPX8xx CPM timer defs	*//* * which CPM timer to use - index starts at 0 (= timer 1) */#define	TID_TIMER_ID	0	/* use CPM timer 1		*//* The portability layer to the virtual timer */static tid_8xx_cpmtimer_t hw;	/* Hardware specific data *//* * WARNING: This code removed from the init_module() function * to demonstrate separation of generic and HW dependant stuff. * This creates the RISK of forgetting to call this function, * which will cause nasty problems because critical initialization * is done here */voidtid_init_timer (Tid_Dev* dev, unsigned long period){  unsigned long immr;		/* Internal Memory Map Register		*/  cpmtimer8xx_t	*cpmtimerp;	/* Pointer to the CPM Timer structure	*/  tid_8xx_cpmtimer_t *hwp = &hw;/* Pointer to private HW data		*/  /*   * register hardware data in generic stucture   */  dev->hw = (void *)hwp;  /*   * Get Pointer to Internal Memory Map   * XXX - could be global symbol for all kernel files   */  asm( "mfspr %0,638": "=r"(immr) : );  immr &= 0xFFFF0000;  /* Pointer to CPM Timer structure */  cpmtimerp = &((immap_t *)immr)->im_cpmtimer;  debugk ("TID: IMMR=0x%lx, TIMERS=0x%x\n", immr, (unsigned)cpmtimerp);  /* Initialize pointers depending on which timer we use */  switch (TID_TIMER_ID) {  case 0: hwp->tmrp = &(cpmtimerp->cpmt_tmr1);	  hwp->trrp = &(cpmtimerp->cpmt_trr1);	  hwp->tcrp = &(cpmtimerp->cpmt_tcr1);	  hwp->tcnp = &(cpmtimerp->cpmt_tcn1);	  hwp->terp = &(cpmtimerp->cpmt_ter1);	  hwp->cpm_vec = CPMVEC_TIMER1;	  break;  case 1: hwp->tmrp = &(cpmtimerp->cpmt_tmr2);	  hwp->trrp = &(cpmtimerp->cpmt_trr2);	  hwp->tcrp = &(cpmtimerp->cpmt_tcr2);	  hwp->tcnp = &(cpmtimerp->cpmt_tcn2);	  hwp->terp = &(cpmtimerp->cpmt_ter2);	  hwp->cpm_vec = CPMVEC_TIMER2;	  break;  case 2: hwp->tmrp = &(cpmtimerp->cpmt_tmr3);	  hwp->trrp = &(cpmtimerp->cpmt_trr3);	  hwp->tcrp = &(cpmtimerp->cpmt_tcr3);	  hwp->tcnp = &(cpmtimerp->cpmt_tcn3);	  hwp->terp = &(cpmtimerp->cpmt_ter3);	  hwp->cpm_vec = CPMVEC_TIMER3;	  break;  case 3: hwp->tmrp = &(cpmtimerp->cpmt_tmr4);	  hwp->trrp = &(cpmtimerp->cpmt_trr4);	  hwp->tcrp = &(cpmtimerp->cpmt_tcr4);	  hwp->tcnp = &(cpmtimerp->cpmt_tcn4);	  hwp->terp = &(cpmtimerp->cpmt_ter4);	  hwp->cpm_vec = CPMVEC_TIMER4;	  break;  }  hwp->tgcrp = &cpmtimerp->cpmt_tgcr;  debugk ("TID: using timer %d\n"	"TID: tgcr @ 0x%x, tmr @ 0x%x, trr @ 0x%x, tcr @ 0x%x, tcn @ 0x%x, ter @ 0x%x\n",	TID_TIMER_ID+1,	(unsigned)hwp->tgcrp,	(unsigned)hwp->tmrp,	(unsigned)hwp->trrp,	(unsigned)hwp->tcrp,	(unsigned)hwp->tcnp,	(unsigned)hwp->terp  );  /* reset timer	*/  *hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);  tid_setPeriod(dev, period);     /* Set period to 1s and start ticking */  /* clear all events */  *hwp->terp = ( CPMT_EVENT_CAP | CPMT_EVENT_REF );  /* Install interrupt handler (enable timer in CIMR) */  cpm_install_handler(hwp->cpm_vec, tid_it_handler, dev);  debugk ("TID: enabling timer\n");  /* enable timer */  *hwp->tgcrp |= (CPMT_GCR_RST << TID_TIMER_ID);  debugk ("TID: tgcr=0x%x, tmr=0x%x, trr=0x%x, tcr=0x%x, tcn=0x%x, ter=0x%x\n",	*hwp->tgcrp, *hwp->tmrp, *hwp->trrp, *hwp->tcrp, *hwp->tcnp, *hwp->terp  );}voidtid_cancel_timer (Tid_Dev* dev){  tid_8xx_cpmtimer_t *hwp = (tid_8xx_cpmtimer_t *)dev->hw;  debugk ("TID: stopping timer\n");  *hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);  /* Uninstall interrupt handler */  cpm_free_handler (hwp->cpm_vec);}inttid_useSimulatedTimer(void){  return 0;     /* we are dealing with real hardware here */}voidtid_ackTimerInterrupt(void *dev_id){  Tid_Dev* dev = (Tid_Dev *)dev_id;  tid_8xx_cpmtimer_t *hwp = (tid_8xx_cpmtimer_t *)dev->hw;  /* just for demonstration */#if 0  printk (".");#endif  /* clear all possible events: Ref. and Cap. */  *hwp->terp = ( CPMT_EVENT_CAP | CPMT_EVENT_REF );}/* Set period in microseconds and start. * Stop if arg is zero. * Truncate to maximum period if more than this is requested - but warn about it. */void tid_setPeriod (Tid_Dev* dev, ulong interval){	unsigned short prescaler;	unsigned long ticks;	tid_8xx_cpmtimer_t *hwp = (tid_8xx_cpmtimer_t *)dev->hw;	debugk ("TID: set interval %ld us\n", interval);	if (interval == 0) {		/* STOP timer */		tid_cancel_timer (dev);		return;	}	/* Warn if requesting longer period than possible */	if (interval > CPMT_MAX_INTERVAL) {		printk ("TID: Truncate interval %ld to maximum (%d)\n",			interval, CPMT_MAX_INTERVAL);		interval = CPMT_MAX_INTERVAL;	}	/*	 * Check if we want to use clock divider:	 * Since the reference counter can be incremented only in integer steps,	 * we try to keep it as big as possible to allow the resulting period to be	 * as precise as possible.	 */	/* prescaler, enable interrupt, restart after ref count is reached */	prescaler = (ushort)((CPMT_PRESCALER-1) << 8) |		    CPMT_MR_ORI |		    CPMT_MR_FRR;	ticks = ((ulong)TQM_CLOCKRATE * interval);	if (ticks > CPMT_MAX_TICKS) {		ticks /= CPMT_CLOCK_DIV;		prescaler |= CPMT_MR_ICLK_CLKDIV; /* use system clock divided by 16 */	} else {		prescaler |= CPMT_MR_ICLK_CLK;  /* use system clock without divider */	}	debugk ("TID: clock/%d, prescale factor %d, reference %ld, ticks %ld\n",		(ticks > CPMT_MAX_TICKS) ? CPMT_CLOCK_DIV : 1,		CPMT_PRESCALER,		(ticks / CPMT_PRESCALER),		ticks	);	/* set prescaler register */	*hwp->tmrp = prescaler;	/* clear timer counter */	*hwp->tcnp = 0;	/* set reference register */	*hwp->trrp = (unsigned short)(ticks / CPMT_PRESCALER);}

⌨️ 快捷键说明

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