root/arch/m68k/hp300/time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hp300_tick
  2. hp300_read_clk
  3. hp300_sched_init

   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/clocksource.h>
  12 #include <linux/types.h>
  13 #include <linux/init.h>
  14 #include <linux/sched.h>
  15 #include <linux/kernel_stat.h>
  16 #include <linux/interrupt.h>
  17 #include <asm/machdep.h>
  18 #include <asm/irq.h>
  19 #include <asm/io.h>
  20 #include <asm/traps.h>
  21 #include <asm/blinken.h>
  22 
  23 static u64 hp300_read_clk(struct clocksource *cs);
  24 
  25 static struct clocksource hp300_clk = {
  26         .name   = "timer",
  27         .rating = 250,
  28         .read   = hp300_read_clk,
  29         .mask   = CLOCKSOURCE_MASK(32),
  30         .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
  31 };
  32 
  33 static u32 clk_total, clk_offset;
  34 
  35 /* Clock hardware definitions */
  36 
  37 #define CLOCKBASE       0xf05f8000
  38 
  39 #define CLKCR1          0x1
  40 #define CLKCR2          0x3
  41 #define CLKCR3          CLKCR1
  42 #define CLKSR           CLKCR2
  43 #define CLKMSB1         0x5
  44 #define CLKLSB1         0x7
  45 #define CLKMSB2         0x9
  46 #define CLKMSB3         0xD
  47 
  48 #define CLKSR_INT1      BIT(0)
  49 
  50 /* This is for machines which generate the exact clock. */
  51 
  52 #define HP300_TIMER_CLOCK_FREQ 250000
  53 #define HP300_TIMER_CYCLES     (HP300_TIMER_CLOCK_FREQ / HZ)
  54 #define INTVAL                 (HP300_TIMER_CYCLES - 1)
  55 
  56 static irqreturn_t hp300_tick(int irq, void *dev_id)
  57 {
  58         irq_handler_t timer_routine = dev_id;
  59         unsigned long flags;
  60         unsigned long tmp;
  61 
  62         local_irq_save(flags);
  63         in_8(CLOCKBASE + CLKSR);
  64         asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
  65         clk_total += INTVAL;
  66         clk_offset = 0;
  67         timer_routine(0, NULL);
  68         local_irq_restore(flags);
  69 
  70         /* Turn off the network and SCSI leds */
  71         blinken_leds(0, 0xe0);
  72         return IRQ_HANDLED;
  73 }
  74 
  75 static u64 hp300_read_clk(struct clocksource *cs)
  76 {
  77         unsigned long flags;
  78         unsigned char lsb, msb, msb_new;
  79         u32 ticks;
  80 
  81         local_irq_save(flags);
  82         /* Read current timer 1 value */
  83         msb = in_8(CLOCKBASE + CLKMSB1);
  84 again:
  85         if ((in_8(CLOCKBASE + CLKSR) & CLKSR_INT1) && msb > 0)
  86                 clk_offset = INTVAL;
  87         lsb = in_8(CLOCKBASE + CLKLSB1);
  88         msb_new = in_8(CLOCKBASE + CLKMSB1);
  89         if (msb_new != msb) {
  90                 msb = msb_new;
  91                 goto again;
  92         }
  93 
  94         ticks = INTVAL - ((msb << 8) | lsb);
  95         ticks += clk_offset + clk_total;
  96         local_irq_restore(flags);
  97 
  98         return ticks;
  99 }
 100 
 101 void __init hp300_sched_init(irq_handler_t vector)
 102 {
 103   out_8(CLOCKBASE + CLKCR2, 0x1);               /* select CR1 */
 104   out_8(CLOCKBASE + CLKCR1, 0x1);               /* reset */
 105 
 106   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 107 
 108   if (request_irq(IRQ_AUTO_6, hp300_tick, IRQF_TIMER, "timer tick", vector))
 109     pr_err("Couldn't register timer interrupt\n");
 110 
 111   out_8(CLOCKBASE + CLKCR2, 0x1);               /* select CR1 */
 112   out_8(CLOCKBASE + CLKCR1, 0x40);              /* enable irq */
 113 
 114   clocksource_register_hz(&hp300_clk, HP300_TIMER_CLOCK_FREQ);
 115 }

/* [<][>][^][v][top][bottom][index][help] */