1 /* 2 * linux/arch/m68k/hp300/time.c 3 * 4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org> 5 * 6 * This file contains the HP300-specific time handling code. 7 */ 8 9 #include <asm/ptrace.h> 10 #include <linux/types.h> 11 #include <linux/init.h> 12 #include <linux/sched.h> 13 #include <linux/kernel_stat.h> 14 #include <linux/interrupt.h> 15 #include <asm/machdep.h> 16 #include <asm/irq.h> 17 #include <asm/io.h> 18 #include <asm/system.h> 19 #include <asm/traps.h> 20 #include <asm/blinken.h> 21 22 /* Clock hardware definitions */ 23 24 #define CLOCKBASE 0xf05f8000 25 26 #define CLKCR1 0x1 27 #define CLKCR2 0x3 28 #define CLKCR3 CLKCR1 29 #define CLKSR CLKCR2 30 #define CLKMSB1 0x5 31 #define CLKMSB2 0x9 32 #define CLKMSB3 0xD 33 34 /* This is for machines which generate the exact clock. */ 35 #define USECS_PER_JIFFY (1000000/HZ) 36 37 #define INTVAL ((10000 / 4) - 1) 38 39 static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs) 40 { 41 unsigned long tmp; 42 irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id; 43 in_8(CLOCKBASE + CLKSR); 44 asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); 45 /* Turn off the network and SCSI leds */ 46 blinken_leds(0, 0xe0); 47 return vector(irq, NULL, regs); 48 } 49 50 unsigned long hp300_gettimeoffset(void) 51 { 52 /* Read current timer 1 value */ 53 unsigned char lsb, msb1, msb2; 54 unsigned short ticks; 55 56 msb1 = in_8(CLOCKBASE + 5); 57 lsb = in_8(CLOCKBASE + 7); 58 msb2 = in_8(CLOCKBASE + 5); 59 if (msb1 != msb2) 60 /* A carry happened while we were reading. Read it again */ 61 lsb = in_8(CLOCKBASE + 7); 62 ticks = INTVAL - ((msb2 << 8) | lsb); 63 return (USECS_PER_JIFFY * ticks) / INTVAL; 64 } 65 66 void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)) 67 { 68 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ 69 out_8(CLOCKBASE + CLKCR1, 0x1); /* reset */ 70 71 asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); 72 73 request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); 74 75 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ 76 out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ 77 } 78