m68k: rename CONFIG_MCFTMR to CFG_MCFTMR
[platform/kernel/u-boot.git] / arch / m68k / lib / time.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
4  *
5  * (C) Copyright 2000
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  */
8
9 #include <common.h>
10 #include <init.h>
11 #include <irq_func.h>
12 #include <time.h>
13 #include <asm/global_data.h>
14 #include <linux/delay.h>
15
16 #include <asm/timer.h>
17 #include <asm/immap.h>
18 #include <watchdog.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 static volatile ulong timestamp = 0;
23
24 #ifndef CFG_SYS_WATCHDOG_FREQ
25 #define CFG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
26 #endif
27
28 #if defined(CFG_MCFTMR)
29 #ifndef CFG_SYS_UDELAY_BASE
30 #       error   "uDelay base not defined!"
31 #endif
32
33 #if !defined(CFG_SYS_TMR_BASE) || !defined(CFG_SYS_INTR_BASE) || !defined(CFG_SYS_TMRINTR_NO) || !defined(CFG_SYS_TMRINTR_MASK)
34 #       error   "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
35 #endif
36 extern void dtimer_intr_setup(void);
37
38 void __udelay(unsigned long usec)
39 {
40         volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_UDELAY_BASE);
41         uint start, now, tmp;
42
43         while (usec > 0) {
44                 if (usec > 65000)
45                         tmp = 65000;
46                 else
47                         tmp = usec;
48                 usec = usec - tmp;
49
50                 /* Set up TIMER 3 as timebase clock */
51                 timerp->tmr = DTIM_DTMR_RST_RST;
52                 timerp->tcn = 0;
53                 /* set period to 1 us */
54                 timerp->tmr =
55                     CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
56                     DTIM_DTMR_RST_EN;
57
58                 start = now = timerp->tcn;
59                 while (now < start + tmp)
60                         now = timerp->tcn;
61         }
62 }
63
64 void dtimer_interrupt(void *not_used)
65 {
66         volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
67
68         /* check for timer interrupt asserted */
69         if ((CFG_SYS_TMRPND_REG & CFG_SYS_TMRINTR_MASK) == CFG_SYS_TMRINTR_PEND) {
70                 timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
71                 timestamp++;
72
73                 #if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
74                 if (CFG_SYS_WATCHDOG_FREQ && (timestamp % (CFG_SYS_WATCHDOG_FREQ)) == 0) {
75                         schedule();
76                 }
77                 #endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
78                 return;
79         }
80 }
81
82 int timer_init(void)
83 {
84         volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
85
86         timestamp = 0;
87
88         timerp->tcn = 0;
89         timerp->trr = 0;
90
91         /* Set up TIMER 4 as clock */
92         timerp->tmr = DTIM_DTMR_RST_RST;
93
94         /* initialize and enable timer interrupt */
95         irq_install_handler(CFG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
96
97         timerp->tcn = 0;
98         timerp->trr = 1000;     /* Interrupt every ms */
99
100         dtimer_intr_setup();
101
102         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
103         timerp->tmr = CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
104             DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
105
106         return 0;
107 }
108
109 ulong get_timer(ulong base)
110 {
111         return (timestamp - base);
112 }
113
114 #endif                          /* CFG_MCFTMR */
115
116 /*
117  * This function is derived from PowerPC code (read timebase as long long).
118  * On M68K it just returns the timer value.
119  */
120 unsigned long long get_ticks(void)
121 {
122         return get_timer(0);
123 }
124
125 unsigned long usec2ticks(unsigned long usec)
126 {
127         return get_timer(usec);
128 }
129
130 /*
131  * This function is derived from PowerPC code (timebase clock frequency).
132  * On M68K it returns the number of timer ticks per second.
133  */
134 ulong get_tbclk(void)
135 {
136         return CONFIG_SYS_HZ;
137 }