2005-04-16 15:20:36 -07:00
/*
* linux / arch / m68k / hp300 / time . c
*
* Copyright ( C ) 1998 Philip Blundell < philb @ gnu . org >
*
* This file contains the HP300 - specific time handling code .
*/
# include <asm/ptrace.h>
# include <linux/types.h>
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/kernel_stat.h>
# include <linux/interrupt.h>
# include <asm/machdep.h>
# include <asm/irq.h>
# include <asm/io.h>
# include <asm/system.h>
# include <asm/traps.h>
# include <asm/blinken.h>
/* Clock hardware definitions */
# define CLOCKBASE 0xf05f8000
# define CLKCR1 0x1
# define CLKCR2 0x3
# define CLKCR3 CLKCR1
# define CLKSR CLKCR2
# define CLKMSB1 0x5
# define CLKMSB2 0x9
# define CLKMSB3 0xD
/* This is for machines which generate the exact clock. */
# define USECS_PER_JIFFY (1000000 / HZ)
# define INTVAL ((10000 / 4) - 1)
2006-10-07 14:16:45 +01:00
static irqreturn_t hp300_tick ( int irq , void * dev_id )
2005-04-16 15:20:36 -07:00
{
unsigned long tmp ;
2006-10-09 12:19:47 +01:00
irq_handler_t vector = dev_id ;
2005-04-16 15:20:36 -07:00
in_8 ( CLOCKBASE + CLKSR ) ;
asm volatile ( " movpw %1@(5) , % 0 " : " = d " (tmp) : " a " (CLOCKBASE)) ;
/* Turn off the network and SCSI leds */
blinken_leds ( 0 , 0xe0 ) ;
2006-10-07 14:16:45 +01:00
return vector ( irq , NULL ) ;
2005-04-16 15:20:36 -07:00
}
unsigned long hp300_gettimeoffset ( void )
{
/* Read current timer 1 value */
unsigned char lsb , msb1 , msb2 ;
unsigned short ticks ;
msb1 = in_8 ( CLOCKBASE + 5 ) ;
lsb = in_8 ( CLOCKBASE + 7 ) ;
msb2 = in_8 ( CLOCKBASE + 5 ) ;
if ( msb1 ! = msb2 )
/* A carry happened while we were reading. Read it again */
lsb = in_8 ( CLOCKBASE + 7 ) ;
ticks = INTVAL - ( ( msb2 < < 8 ) | lsb ) ;
return ( USECS_PER_JIFFY * ticks ) / INTVAL ;
}
2006-10-09 12:19:47 +01:00
void __init hp300_sched_init ( irq_handler_t vector )
2005-04-16 15:20:36 -07:00
{
out_8 ( CLOCKBASE + CLKCR2 , 0x1 ) ; /* select CR1 */
out_8 ( CLOCKBASE + CLKCR1 , 0x1 ) ; /* reset */
asm volatile ( " movpw %0,%1@(5) " : : " d " (INTVAL), " a " (CLOCKBASE)) ;
2011-07-13 22:33:13 +02:00
if ( request_irq ( IRQ_AUTO_6 , hp300_tick , 0 , " timer tick " , vector ) )
2008-12-30 14:02:06 +01:00
pr_err ( " Couldn't register timer interrupt \n " ) ;
2005-04-16 15:20:36 -07:00
out_8 ( CLOCKBASE + CLKCR2 , 0x1 ) ; /* select CR1 */
out_8 ( CLOCKBASE + CLKCR1 , 0x40 ) ; /* enable irq */
}