1*4882a593Smuzhiyun /***************************************************************************/
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun /*
4*4882a593Smuzhiyun * timers.c - Generic hardware timer support.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 1993 Hamish Macdonald
7*4882a593Smuzhiyun * Copyright (C) 1999 D. Jeff Dionne
8*4882a593Smuzhiyun * Copyright (C) 2001 Georges Menie, Ken Desmet
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
11*4882a593Smuzhiyun * License. See the file COPYING in the main directory of this archive
12*4882a593Smuzhiyun * for more details.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /***************************************************************************/
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/mm.h>
20*4882a593Smuzhiyun #include <linux/interrupt.h>
21*4882a593Smuzhiyun #include <linux/irq.h>
22*4882a593Smuzhiyun #include <linux/clocksource.h>
23*4882a593Smuzhiyun #include <linux/rtc.h>
24*4882a593Smuzhiyun #include <asm/setup.h>
25*4882a593Smuzhiyun #include <asm/machdep.h>
26*4882a593Smuzhiyun #include <asm/MC68VZ328.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /***************************************************************************/
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #if defined(CONFIG_DRAGEN2)
31*4882a593Smuzhiyun /* with a 33.16 MHz clock, this will give usec resolution to the time functions */
32*4882a593Smuzhiyun #define CLOCK_SOURCE TCTL_CLKSOURCE_SYSCLK
33*4882a593Smuzhiyun #define CLOCK_PRE 7
34*4882a593Smuzhiyun #define TICKS_PER_JIFFY 41450
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #elif defined(CONFIG_XCOPILOT_BUGS)
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun * The only thing I know is that CLK32 is not available on Xcopilot
39*4882a593Smuzhiyun * I have little idea about what frequency SYSCLK has on Xcopilot.
40*4882a593Smuzhiyun * The values for prescaler and compare registers were simply
41*4882a593Smuzhiyun * taken from the original source
42*4882a593Smuzhiyun */
43*4882a593Smuzhiyun #define CLOCK_SOURCE TCTL_CLKSOURCE_SYSCLK
44*4882a593Smuzhiyun #define CLOCK_PRE 2
45*4882a593Smuzhiyun #define TICKS_PER_JIFFY 0xd7e4
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #else
48*4882a593Smuzhiyun /* default to using the 32Khz clock */
49*4882a593Smuzhiyun #define CLOCK_SOURCE TCTL_CLKSOURCE_32KHZ
50*4882a593Smuzhiyun #define CLOCK_PRE 31
51*4882a593Smuzhiyun #define TICKS_PER_JIFFY 10
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static u32 m68328_tick_cnt;
55*4882a593Smuzhiyun static irq_handler_t timer_interrupt;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /***************************************************************************/
58*4882a593Smuzhiyun
hw_tick(int irq,void * dummy)59*4882a593Smuzhiyun static irqreturn_t hw_tick(int irq, void *dummy)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun /* Reset Timer1 */
62*4882a593Smuzhiyun TSTAT &= 0;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun m68328_tick_cnt += TICKS_PER_JIFFY;
65*4882a593Smuzhiyun return timer_interrupt(irq, dummy);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /***************************************************************************/
69*4882a593Smuzhiyun
m68328_read_clk(struct clocksource * cs)70*4882a593Smuzhiyun static u64 m68328_read_clk(struct clocksource *cs)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun unsigned long flags;
73*4882a593Smuzhiyun u32 cycles;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun local_irq_save(flags);
76*4882a593Smuzhiyun cycles = m68328_tick_cnt + TCN;
77*4882a593Smuzhiyun local_irq_restore(flags);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun return cycles;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /***************************************************************************/
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun static struct clocksource m68328_clk = {
85*4882a593Smuzhiyun .name = "timer",
86*4882a593Smuzhiyun .rating = 250,
87*4882a593Smuzhiyun .read = m68328_read_clk,
88*4882a593Smuzhiyun .mask = CLOCKSOURCE_MASK(32),
89*4882a593Smuzhiyun .flags = CLOCK_SOURCE_IS_CONTINUOUS,
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /***************************************************************************/
93*4882a593Smuzhiyun
hw_timer_init(irq_handler_t handler)94*4882a593Smuzhiyun void hw_timer_init(irq_handler_t handler)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun int ret;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* disable timer 1 */
99*4882a593Smuzhiyun TCTL = 0;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /* set ISR */
102*4882a593Smuzhiyun ret = request_irq(TMR_IRQ_NUM, hw_tick, IRQF_TIMER, "timer", NULL);
103*4882a593Smuzhiyun if (ret) {
104*4882a593Smuzhiyun pr_err("Failed to request irq %d (timer): %pe\n", TMR_IRQ_NUM,
105*4882a593Smuzhiyun ERR_PTR(ret));
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* Restart mode, Enable int, Set clock source */
109*4882a593Smuzhiyun TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
110*4882a593Smuzhiyun TPRER = CLOCK_PRE;
111*4882a593Smuzhiyun TCMP = TICKS_PER_JIFFY;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* Enable timer 1 */
114*4882a593Smuzhiyun TCTL |= TCTL_TEN;
115*4882a593Smuzhiyun clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ);
116*4882a593Smuzhiyun timer_interrupt = handler;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /***************************************************************************/
120*4882a593Smuzhiyun
m68328_hwclk(int set,struct rtc_time * t)121*4882a593Smuzhiyun int m68328_hwclk(int set, struct rtc_time *t)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun if (!set) {
124*4882a593Smuzhiyun long now = RTCTIME;
125*4882a593Smuzhiyun t->tm_year = 1;
126*4882a593Smuzhiyun t->tm_mon = 0;
127*4882a593Smuzhiyun t->tm_mday = 1;
128*4882a593Smuzhiyun t->tm_hour = (now >> 24) % 24;
129*4882a593Smuzhiyun t->tm_min = (now >> 16) % 60;
130*4882a593Smuzhiyun t->tm_sec = now % 60;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /***************************************************************************/
137