xref: /openbmc/linux/arch/m68k/68000/timers.c (revision a5a1d1c2)
118cb3fafSGreg Ungerer /***************************************************************************/
218cb3fafSGreg Ungerer 
318cb3fafSGreg Ungerer /*
418cb3fafSGreg Ungerer  *  timers.c - Generic hardware timer support.
518cb3fafSGreg Ungerer  *
618cb3fafSGreg Ungerer  *  Copyright (C) 1993 Hamish Macdonald
718cb3fafSGreg Ungerer  *  Copyright (C) 1999 D. Jeff Dionne
818cb3fafSGreg Ungerer  *  Copyright (C) 2001 Georges Menie, Ken Desmet
918cb3fafSGreg Ungerer  *
1018cb3fafSGreg Ungerer  * This file is subject to the terms and conditions of the GNU General Public
1118cb3fafSGreg Ungerer  * License.  See the file COPYING in the main directory of this archive
1218cb3fafSGreg Ungerer  * for more details.
1318cb3fafSGreg Ungerer  */
1418cb3fafSGreg Ungerer 
1518cb3fafSGreg Ungerer /***************************************************************************/
1618cb3fafSGreg Ungerer 
1718cb3fafSGreg Ungerer #include <linux/types.h>
1818cb3fafSGreg Ungerer #include <linux/kernel.h>
1918cb3fafSGreg Ungerer #include <linux/mm.h>
2018cb3fafSGreg Ungerer #include <linux/interrupt.h>
2118cb3fafSGreg Ungerer #include <linux/irq.h>
2218cb3fafSGreg Ungerer #include <linux/clocksource.h>
2318cb3fafSGreg Ungerer #include <linux/rtc.h>
2418cb3fafSGreg Ungerer #include <asm/setup.h>
2518cb3fafSGreg Ungerer #include <asm/pgtable.h>
2618cb3fafSGreg Ungerer #include <asm/machdep.h>
2718cb3fafSGreg Ungerer #include <asm/MC68VZ328.h>
2818cb3fafSGreg Ungerer 
2918cb3fafSGreg Ungerer /***************************************************************************/
3018cb3fafSGreg Ungerer 
3118cb3fafSGreg Ungerer #if defined(CONFIG_DRAGEN2)
3218cb3fafSGreg Ungerer /* with a 33.16 MHz clock, this will give usec resolution to the time functions */
3318cb3fafSGreg Ungerer #define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
3418cb3fafSGreg Ungerer #define CLOCK_PRE	7
3518cb3fafSGreg Ungerer #define TICKS_PER_JIFFY	41450
3618cb3fafSGreg Ungerer 
3718cb3fafSGreg Ungerer #elif defined(CONFIG_XCOPILOT_BUGS)
3818cb3fafSGreg Ungerer /*
3918cb3fafSGreg Ungerer  * The only thing I know is that CLK32 is not available on Xcopilot
4018cb3fafSGreg Ungerer  * I have little idea about what frequency SYSCLK has on Xcopilot.
4118cb3fafSGreg Ungerer  * The values for prescaler and compare registers were simply
4218cb3fafSGreg Ungerer  * taken from the original source
4318cb3fafSGreg Ungerer  */
4418cb3fafSGreg Ungerer #define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
4518cb3fafSGreg Ungerer #define CLOCK_PRE	2
4618cb3fafSGreg Ungerer #define TICKS_PER_JIFFY	0xd7e4
4718cb3fafSGreg Ungerer 
4818cb3fafSGreg Ungerer #else
4918cb3fafSGreg Ungerer /* default to using the 32Khz clock */
5018cb3fafSGreg Ungerer #define CLOCK_SOURCE	TCTL_CLKSOURCE_32KHZ
5118cb3fafSGreg Ungerer #define CLOCK_PRE	31
5218cb3fafSGreg Ungerer #define TICKS_PER_JIFFY	10
5318cb3fafSGreg Ungerer #endif
5418cb3fafSGreg Ungerer 
5518cb3fafSGreg Ungerer static u32 m68328_tick_cnt;
5618cb3fafSGreg Ungerer static irq_handler_t timer_interrupt;
5718cb3fafSGreg Ungerer 
5818cb3fafSGreg Ungerer /***************************************************************************/
5918cb3fafSGreg Ungerer 
6018cb3fafSGreg Ungerer static irqreturn_t hw_tick(int irq, void *dummy)
6118cb3fafSGreg Ungerer {
6218cb3fafSGreg Ungerer 	/* Reset Timer1 */
6318cb3fafSGreg Ungerer 	TSTAT &= 0;
6418cb3fafSGreg Ungerer 
6518cb3fafSGreg Ungerer 	m68328_tick_cnt += TICKS_PER_JIFFY;
6618cb3fafSGreg Ungerer 	return timer_interrupt(irq, dummy);
6718cb3fafSGreg Ungerer }
6818cb3fafSGreg Ungerer 
6918cb3fafSGreg Ungerer /***************************************************************************/
7018cb3fafSGreg Ungerer 
7118cb3fafSGreg Ungerer static struct irqaction m68328_timer_irq = {
7218cb3fafSGreg Ungerer 	.name	 = "timer",
7318cb3fafSGreg Ungerer 	.flags	 = IRQF_TIMER,
7418cb3fafSGreg Ungerer 	.handler = hw_tick,
7518cb3fafSGreg Ungerer };
7618cb3fafSGreg Ungerer 
7718cb3fafSGreg Ungerer /***************************************************************************/
7818cb3fafSGreg Ungerer 
79a5a1d1c2SThomas Gleixner static u64 m68328_read_clk(struct clocksource *cs)
8018cb3fafSGreg Ungerer {
8118cb3fafSGreg Ungerer 	unsigned long flags;
8218cb3fafSGreg Ungerer 	u32 cycles;
8318cb3fafSGreg Ungerer 
8418cb3fafSGreg Ungerer 	local_irq_save(flags);
8518cb3fafSGreg Ungerer 	cycles = m68328_tick_cnt + TCN;
8618cb3fafSGreg Ungerer 	local_irq_restore(flags);
8718cb3fafSGreg Ungerer 
8818cb3fafSGreg Ungerer 	return cycles;
8918cb3fafSGreg Ungerer }
9018cb3fafSGreg Ungerer 
9118cb3fafSGreg Ungerer /***************************************************************************/
9218cb3fafSGreg Ungerer 
9318cb3fafSGreg Ungerer static struct clocksource m68328_clk = {
9418cb3fafSGreg Ungerer 	.name	= "timer",
9518cb3fafSGreg Ungerer 	.rating	= 250,
9618cb3fafSGreg Ungerer 	.read	= m68328_read_clk,
9718cb3fafSGreg Ungerer 	.mask	= CLOCKSOURCE_MASK(32),
9818cb3fafSGreg Ungerer 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
9918cb3fafSGreg Ungerer };
10018cb3fafSGreg Ungerer 
10118cb3fafSGreg Ungerer /***************************************************************************/
10218cb3fafSGreg Ungerer 
10318cb3fafSGreg Ungerer void hw_timer_init(irq_handler_t handler)
10418cb3fafSGreg Ungerer {
10518cb3fafSGreg Ungerer 	/* disable timer 1 */
10618cb3fafSGreg Ungerer 	TCTL = 0;
10718cb3fafSGreg Ungerer 
10818cb3fafSGreg Ungerer 	/* set ISR */
10918cb3fafSGreg Ungerer 	setup_irq(TMR_IRQ_NUM, &m68328_timer_irq);
11018cb3fafSGreg Ungerer 
11118cb3fafSGreg Ungerer 	/* Restart mode, Enable int, Set clock source */
11218cb3fafSGreg Ungerer 	TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
11318cb3fafSGreg Ungerer 	TPRER = CLOCK_PRE;
11418cb3fafSGreg Ungerer 	TCMP = TICKS_PER_JIFFY;
11518cb3fafSGreg Ungerer 
11618cb3fafSGreg Ungerer 	/* Enable timer 1 */
11718cb3fafSGreg Ungerer 	TCTL |= TCTL_TEN;
11818cb3fafSGreg Ungerer 	clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ);
11918cb3fafSGreg Ungerer 	timer_interrupt = handler;
12018cb3fafSGreg Ungerer }
12118cb3fafSGreg Ungerer 
12218cb3fafSGreg Ungerer /***************************************************************************/
12318cb3fafSGreg Ungerer 
12418cb3fafSGreg Ungerer int m68328_hwclk(int set, struct rtc_time *t)
12518cb3fafSGreg Ungerer {
12618cb3fafSGreg Ungerer 	if (!set) {
12718cb3fafSGreg Ungerer 		long now = RTCTIME;
12818cb3fafSGreg Ungerer 		t->tm_year = t->tm_mon = t->tm_mday = 1;
12918cb3fafSGreg Ungerer 		t->tm_hour = (now >> 24) % 24;
13018cb3fafSGreg Ungerer 		t->tm_min = (now >> 16) % 60;
13118cb3fafSGreg Ungerer 		t->tm_sec = now % 60;
13218cb3fafSGreg Ungerer 	}
13318cb3fafSGreg Ungerer 
13418cb3fafSGreg Ungerer 	return 0;
13518cb3fafSGreg Ungerer }
13618cb3fafSGreg Ungerer 
13718cb3fafSGreg Ungerer /***************************************************************************/
138