mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 12:08:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			316 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
 | |
|  *
 | |
|  * (C) Copyright 2000
 | |
|  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 | |
|  *
 | |
|  * See file CREDITS for list of people who contributed to this
 | |
|  * project.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License as
 | |
|  * published by the Free Software Foundation; either version 2 of
 | |
|  * the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This program 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 General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | |
|  * MA 02111-1307 USA
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| 
 | |
| #include <asm/mcftimer.h>
 | |
| 
 | |
| #ifdef	CONFIG_M5271
 | |
| #include <asm/m5271.h>
 | |
| #include <asm/immap_5271.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef	CONFIG_M5272
 | |
| #include <asm/m5272.h>
 | |
| #include <asm/immap_5272.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef	CONFIG_M5282
 | |
| #include <asm/m5282.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef	CONFIG_M5249
 | |
| #include <asm/m5249.h>
 | |
| #include <asm/immap_5249.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static ulong timestamp;
 | |
| #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
 | |
| static unsigned short lastinc;
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #if defined(CONFIG_M5272)
 | |
| /*
 | |
|  * We use timer 3 which is running with a period of 1 us
 | |
|  */
 | |
| void udelay(unsigned long usec)
 | |
| {
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
 | |
| 	uint start, now, tmp;
 | |
| 
 | |
| 	while (usec > 0) {
 | |
| 		if (usec > 65000)
 | |
| 			tmp = 65000;
 | |
| 		else
 | |
| 			tmp = usec;
 | |
| 		usec = usec - tmp;
 | |
| 
 | |
| 		/* Set up TIMER 3 as timebase clock */
 | |
| 		timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
 | |
| 		timerp->timer_tcn = 0;
 | |
| 		/* set period to 1 us */
 | |
| 		timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)	<< 8) | MCFTIMER_TMR_CLK1 |
 | |
| 				     MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
 | |
| 
 | |
| 		start = now = timerp->timer_tcn;
 | |
| 		while (now < start + tmp)
 | |
| 			now = timerp->timer_tcn;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void mcf_timer_interrupt (void * not_used){
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
 | |
| 	volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
 | |
| 
 | |
| 	/* check for timer 4 interrupts */
 | |
| 	if ((intp->int_isr & 0x01000000) != 0) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	/* reset timer */
 | |
| 	timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
 | |
| 	timestamp ++;
 | |
| }
 | |
| 
 | |
| void timer_init (void) {
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
 | |
| 	volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
 | |
| 
 | |
| 	timestamp = 0;
 | |
| 
 | |
| 	/* Set up TIMER 4 as clock */
 | |
| 	timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
 | |
| 
 | |
| 	/* initialize and enable timer 4 interrupt */
 | |
| 	irq_install_handler (72, mcf_timer_interrupt, 0);
 | |
| 	intp->int_icr1 |= 0x0000000d;
 | |
| 
 | |
| 	timerp->timer_tcn = 0;
 | |
| 	timerp->timer_trr = 1000;	/* Interrupt every ms */
 | |
| 	/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
 | |
| 	timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)	<< 8) | MCFTIMER_TMR_CLK1 |
 | |
| 		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
 | |
| }
 | |
| 
 | |
| void reset_timer (void)
 | |
| {
 | |
| 	timestamp = 0;
 | |
| }
 | |
| 
 | |
| ulong get_timer (ulong base)
 | |
| {
 | |
| 	return (timestamp - base);
 | |
| }
 | |
| 
 | |
| void set_timer (ulong t)
 | |
| {
 | |
| 	timestamp = t;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
 | |
| 
 | |
| void udelay(unsigned long usec)
 | |
| {
 | |
| 	volatile unsigned short *timerp;
 | |
| 	uint tmp;
 | |
| 
 | |
| 	timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE3);
 | |
| 
 | |
| 	while (usec > 0) {
 | |
| 		if (usec > 65000)
 | |
| 			tmp = 65000;
 | |
| 		else
 | |
| 			tmp = usec;
 | |
| 		usec = usec - tmp;
 | |
| 
 | |
| 		/* Set up TIMER 3 as timebase clock */
 | |
| 		timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
 | |
| 		timerp[MCFTIMER_PMR] = 0;
 | |
| 		/* set period to 1 us */
 | |
| 		timerp[MCFTIMER_PCSR] =
 | |
| #ifdef CONFIG_M5271
 | |
| 			(6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
 | |
| #else /* !CONFIG_M5271 */
 | |
| 			(5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
 | |
| #endif /* CONFIG_M5271 */
 | |
| 
 | |
| 		timerp[MCFTIMER_PMR] = tmp;
 | |
| 		while (timerp[MCFTIMER_PCNTR] > 0);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void timer_init (void)
 | |
| {
 | |
| 	volatile unsigned short *timerp;
 | |
| 
 | |
| 	timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
 | |
| 	timestamp = 0;
 | |
| 
 | |
| 	/* Set up TIMER 4 as poll clock */
 | |
| 	timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
 | |
| 	timerp[MCFTIMER_PMR] = lastinc = 0;
 | |
| 	timerp[MCFTIMER_PCSR] =
 | |
| #ifdef CONFIG_M5271
 | |
| 		(6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
 | |
| #else /* !CONFIG_M5271 */
 | |
| 		(5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
 | |
| #endif /* CONFIG_M5271 */
 | |
| }
 | |
| 
 | |
| void set_timer (ulong t)
 | |
| {
 | |
| 	volatile unsigned short *timerp;
 | |
| 
 | |
| 	timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
 | |
| 	timestamp = 0;
 | |
| 	timerp[MCFTIMER_PMR] = lastinc = 0;
 | |
| }
 | |
| 
 | |
| ulong get_timer (ulong base)
 | |
| {
 | |
| 	unsigned short now, diff;
 | |
| 	volatile unsigned short *timerp;
 | |
| 
 | |
| 	timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
 | |
| 	now = timerp[MCFTIMER_PCNTR];
 | |
| 	diff = -(now - lastinc);
 | |
| 
 | |
| 	timestamp += diff;
 | |
| 	lastinc = now;
 | |
| 	return timestamp - base;
 | |
| }
 | |
| 
 | |
| void wait_ticks (unsigned long ticks)
 | |
| {
 | |
| 	set_timer (0);
 | |
| 	while (get_timer (0) < ticks);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #if defined(CONFIG_M5249)
 | |
| /*
 | |
|  * We use timer 1 which is running with a period of 1 us
 | |
|  */
 | |
| void udelay(unsigned long usec)
 | |
| {
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE1);
 | |
| 	uint start, now, tmp;
 | |
| 
 | |
| 	while (usec > 0) {
 | |
| 		if (usec > 65000)
 | |
| 			tmp = 65000;
 | |
| 		else
 | |
| 			tmp = usec;
 | |
| 		usec = usec - tmp;
 | |
| 
 | |
| 		/* Set up TIMER 1 as timebase clock */
 | |
| 		timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
 | |
| 		timerp->timer_tcn = 0;
 | |
| 		/* set period to 1 us */
 | |
| 		/* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
 | |
| 		timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)	<< 8) | MCFTIMER_TMR_CLK1 |
 | |
| 				     MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
 | |
| 
 | |
| 		start = now = timerp->timer_tcn;
 | |
| 		while (now < start + tmp)
 | |
| 			now = timerp->timer_tcn;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void mcf_timer_interrupt (void * not_used){
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
 | |
| 
 | |
| 	/* check for timer 2 interrupts */
 | |
| 	if ((mbar_readLong(MCFSIM_IPR) & 0x00000400) == 0) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	/* reset timer */
 | |
| 	timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
 | |
| 	timestamp ++;
 | |
| }
 | |
| 
 | |
| void timer_init (void) {
 | |
| 	volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
 | |
| 
 | |
| 	timestamp = 0;
 | |
| 
 | |
| 	/* Set up TIMER 2 as clock */
 | |
| 	timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
 | |
| 
 | |
| 	/* initialize and enable timer 2 interrupt */
 | |
| 	irq_install_handler (31, mcf_timer_interrupt, 0);
 | |
| 	mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
 | |
| 	mbar_writeByte(MCFSIM_TIMER2ICR, MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3);
 | |
| 
 | |
| 	timerp->timer_tcn = 0;
 | |
| 	timerp->timer_trr = 1000;	/* Interrupt every ms */
 | |
| 	/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
 | |
| 	/* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
 | |
| 	timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)	<< 8) | MCFTIMER_TMR_CLK1 |
 | |
| 		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
 | |
| }
 | |
| 
 | |
| void reset_timer (void)
 | |
| {
 | |
| 	timestamp = 0;
 | |
| }
 | |
| 
 | |
| ulong get_timer (ulong base)
 | |
| {
 | |
| 	return (timestamp - base);
 | |
| }
 | |
| 
 | |
| void set_timer (ulong t)
 | |
| {
 | |
| 	timestamp = t;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * This function is derived from PowerPC code (read timebase as long long).
 | |
|  * On M68K it just returns the timer value.
 | |
|  */
 | |
| unsigned long long get_ticks(void)
 | |
| {
 | |
| 	return get_timer(0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * This function is derived from PowerPC code (timebase clock frequency).
 | |
|  * On M68K it returns the number of timer ticks per second.
 | |
|  */
 | |
| ulong get_tbclk (void)
 | |
| {
 | |
| 	ulong tbclk;
 | |
| 	tbclk = CFG_HZ;
 | |
| 	return tbclk;
 | |
| }
 |