blob: 33b4cff4ec7213a6760542937668e3c820eb93d9 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
TsiChungLiew8999e6b2008-01-15 13:37:34 -06002/*
Alison Wang027f76f2012-03-26 21:49:07 +00003 * (C) Copyright 2007, 2012 Freescale Semiconductor, Inc.
TsiChungLiew8999e6b2008-01-15 13:37:34 -06004 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
TsiChungLiew8999e6b2008-01-15 13:37:34 -06005 */
6
7#include <common.h>
Simon Glass97589732020-05-10 11:40:02 -06008#include <init.h>
Simon Glass9b61c7c2019-11-14 12:57:41 -07009#include <irq_func.h>
Simon Glassdbd79542020-05-10 11:40:11 -060010#include <linux/delay.h>
TsiChungLiew8999e6b2008-01-15 13:37:34 -060011
12#include <asm/timer.h>
13#include <asm/immap.h>
Alison Wang027f76f2012-03-26 21:49:07 +000014#include <asm/io.h>
TsiChungLiew8999e6b2008-01-15 13:37:34 -060015
16DECLARE_GLOBAL_DATA_PTR;
17
18static ulong timestamp;
19
20#if defined(CONFIG_SLTTMR)
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020021#ifndef CONFIG_SYS_UDELAY_BASE
TsiChungLiew8999e6b2008-01-15 13:37:34 -060022# error "uDelay base not defined!"
23#endif
24
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020025#if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
TsiChungLiew8999e6b2008-01-15 13:37:34 -060026# error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
27#endif
28extern void dtimer_intr_setup(void);
29
Ingo van Lilf0f778a2009-11-24 14:09:21 +010030void __udelay(unsigned long usec)
TsiChungLiew8999e6b2008-01-15 13:37:34 -060031{
Alison Wang027f76f2012-03-26 21:49:07 +000032 slt_t *timerp = (slt_t *) (CONFIG_SYS_UDELAY_BASE);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060033 u32 now, freq;
34
35 /* 1 us period */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020036 freq = CONFIG_SYS_TIMER_PRESCALER;
TsiChungLiew8999e6b2008-01-15 13:37:34 -060037
Alison Wang027f76f2012-03-26 21:49:07 +000038 /* Disable */
39 out_be32(&timerp->cr, 0);
40 out_be32(&timerp->tcnt, usec * freq);
41 out_be32(&timerp->cr, SLT_CR_TEN);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060042
Alison Wang027f76f2012-03-26 21:49:07 +000043 now = in_be32(&timerp->cnt);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060044 while (now != 0)
Alison Wang027f76f2012-03-26 21:49:07 +000045 now = in_be32(&timerp->cnt);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060046
Alison Wang027f76f2012-03-26 21:49:07 +000047 setbits_be32(&timerp->sr, SLT_SR_ST);
48 out_be32(&timerp->cr, 0);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060049}
50
51void dtimer_interrupt(void *not_used)
52{
Alison Wang027f76f2012-03-26 21:49:07 +000053 slt_t *timerp = (slt_t *) (CONFIG_SYS_TMR_BASE);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060054
55 /* check for timer interrupt asserted */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020056 if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
Alison Wang027f76f2012-03-26 21:49:07 +000057 setbits_be32(&timerp->sr, SLT_SR_ST);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060058 timestamp++;
59 return;
60 }
61}
62
Jason Jin1dd491e2011-08-19 10:02:32 +080063int timer_init(void)
TsiChungLiew8999e6b2008-01-15 13:37:34 -060064{
Alison Wang027f76f2012-03-26 21:49:07 +000065 slt_t *timerp = (slt_t *) (CONFIG_SYS_TMR_BASE);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060066
67 timestamp = 0;
68
Alison Wang027f76f2012-03-26 21:49:07 +000069 /* disable timer */
70 out_be32(&timerp->cr, 0);
71 out_be32(&timerp->tcnt, 0);
72 /* clear status */
73 out_be32(&timerp->sr, SLT_SR_BE | SLT_SR_ST);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060074
75 /* initialize and enable timer interrupt */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020076 irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060077
78 /* Interrupt every ms */
Alison Wang027f76f2012-03-26 21:49:07 +000079 out_be32(&timerp->tcnt, 1000 * CONFIG_SYS_TIMER_PRESCALER);
TsiChungLiew8999e6b2008-01-15 13:37:34 -060080
81 dtimer_intr_setup();
82
83 /* set a period of 1us, set timer mode to restart and
84 enable timer and interrupt */
Alison Wang027f76f2012-03-26 21:49:07 +000085 out_be32(&timerp->cr, SLT_CR_RUN | SLT_CR_IEN | SLT_CR_TEN);
Jason Jin1dd491e2011-08-19 10:02:32 +080086 return 0;
TsiChungLiew8999e6b2008-01-15 13:37:34 -060087}
88
TsiChungLiew8999e6b2008-01-15 13:37:34 -060089ulong get_timer(ulong base)
90{
91 return (timestamp - base);
92}
93
TsiChungLiew8999e6b2008-01-15 13:37:34 -060094#endif /* CONFIG_SLTTMR */