linux/arch/arm/mach-footbridge/isa-timer.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-footbridge/isa-timer.c
   3 *
   4 *  Copyright (C) 1998 Russell King.
   5 *  Copyright (C) 1998 Phil Blundell
   6 */
   7#include <linux/init.h>
   8#include <linux/interrupt.h>
   9#include <linux/irq.h>
  10#include <linux/io.h>
  11
  12#include <asm/irq.h>
  13
  14#include <asm/mach/time.h>
  15
  16#include "common.h"
  17
  18/*
  19 * ISA timer tick support
  20 */
  21#define mSEC_10_from_14 ((14318180 + 100) / 200)
  22
  23static unsigned long isa_gettimeoffset(void)
  24{
  25        int count;
  26
  27        static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
  28        static unsigned long jiffies_p = 0;
  29
  30        /*
  31         * cache volatile jiffies temporarily; we have IRQs turned off. 
  32         */
  33        unsigned long jiffies_t;
  34
  35        /* timer count may underflow right here */
  36        outb_p(0x00, 0x43);     /* latch the count ASAP */
  37
  38        count = inb_p(0x40);    /* read the latched count */
  39
  40        /*
  41         * We do this guaranteed double memory access instead of a _p 
  42         * postfix in the previous port access. Wheee, hackady hack
  43         */
  44        jiffies_t = jiffies;
  45
  46        count |= inb_p(0x40) << 8;
  47
  48        /* Detect timer underflows.  If we haven't had a timer tick since 
  49           the last time we were called, and time is apparently going
  50           backwards, the counter must have wrapped during this routine. */
  51        if ((jiffies_t == jiffies_p) && (count > count_p))
  52                count -= (mSEC_10_from_14/6);
  53        else
  54                jiffies_p = jiffies_t;
  55
  56        count_p = count;
  57
  58        count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
  59        count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
  60
  61        return count;
  62}
  63
  64static irqreturn_t
  65isa_timer_interrupt(int irq, void *dev_id)
  66{
  67        timer_tick();
  68        return IRQ_HANDLED;
  69}
  70
  71static struct irqaction isa_timer_irq = {
  72        .name           = "ISA timer tick",
  73        .handler        = isa_timer_interrupt,
  74        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  75};
  76
  77static void __init isa_timer_init(void)
  78{
  79        isa_rtc_init();
  80
  81        /* enable PIT timer */
  82        /* set for periodic (4) and LSB/MSB write (0x30) */
  83        outb(0x34, 0x43);
  84        outb((mSEC_10_from_14/6) & 0xFF, 0x40);
  85        outb((mSEC_10_from_14/6) >> 8, 0x40);
  86
  87        setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
  88}
  89
  90struct sys_timer isa_timer = {
  91        .init           = isa_timer_init,
  92        .offset         = isa_gettimeoffset,
  93};
  94