xref: /OK3568_Linux_fs/kernel/arch/m68k/68000/timers.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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