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 #include "ints.h" 22 23 /* Clock hardware definitions */ 24 25 #define CLOCKBASE 0xf05f8000 26 27 #define CLKCR1 0x1 28 #define CLKCR2 0x3 29 #define CLKCR3 CLKCR1 30 #define CLKSR CLKCR2 31 #define CLKMSB1 0x5 32 #define CLKMSB2 0x9 33 #define CLKMSB3 0xD 34 35 /* This is for machines which generate the exact clock. */ 36 #define USECS_PER_JIFFY (1000000/HZ) 37 38 #define INTVAL ((10000 / 4) - 1) 39 40 static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs) 41 { 42 unsigned long tmp; 43 irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id; 44 in_8(CLOCKBASE + CLKSR); 45 asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); 46 /* Turn off the network and SCSI leds */ 47 blinken_leds(0, 0xe0); 48 return vector(irq, NULL, regs); 49 } 50 51 unsigned long hp300_gettimeoffset(void) 52 { 53 /* Read current timer 1 value */ 54 unsigned char lsb, msb1, msb2; 55 unsigned short ticks; 56 57 msb1 = in_8(CLOCKBASE + 5); 58 lsb = in_8(CLOCKBASE + 7); 59 msb2 = in_8(CLOCKBASE + 5); 60 if (msb1 != msb2) 61 /* A carry happened while we were reading. Read it again */ 62 lsb = in_8(CLOCKBASE + 7); 63 ticks = INTVAL - ((msb2 << 8) | lsb); 64 return (USECS_PER_JIFFY * ticks) / INTVAL; 65 } 66 67 void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)) 68 { 69 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ 70 out_8(CLOCKBASE + CLKCR1, 0x1); /* reset */ 71 72 asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); 73 74 cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); 75 76 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ 77 out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ 78 } 79