1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/arch/m68k/hp300/time.c 4 * 5 * Copyright (C) 1998 Philip Blundell <philb@gnu.org> 6 * 7 * This file contains the HP300-specific time handling code. 8 */ 9 10 #include <asm/ptrace.h> 11 #include <linux/types.h> 12 #include <linux/init.h> 13 #include <linux/sched.h> 14 #include <linux/kernel_stat.h> 15 #include <linux/interrupt.h> 16 #include <asm/machdep.h> 17 #include <asm/irq.h> 18 #include <asm/io.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) 40 { 41 unsigned long tmp; 42 irq_handler_t vector = 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); 48 } 49 50 u32 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) * 1000; 64 } 65 66 void __init hp300_sched_init(irq_handler_t vector) 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 if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector)) 74 pr_err("Couldn't register timer interrupt\n"); 75 76 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ 77 out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ 78 } 79