isa-timer.c 2.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/*
 *  linux/arch/arm/mach-footbridge/isa-timer.c
 *
 *  Copyright (C) 1998 Russell King.
 *  Copyright (C) 1998 Phil Blundell
 */
#include <linux/init.h>
#include <linux/interrupt.h>
9
#include <linux/irq.h>
10
#include <linux/io.h>
L
Linus Torvalds 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

#include <asm/irq.h>

#include <asm/mach/time.h>

#include "common.h"

/*
 * ISA timer tick support
 */
#define mSEC_10_from_14 ((14318180 + 100) / 200)

static unsigned long isa_gettimeoffset(void)
{
	int count;

	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
	static unsigned long jiffies_p = 0;

	/*
	 * cache volatile jiffies temporarily; we have IRQs turned off. 
	 */
	unsigned long jiffies_t;

	/* timer count may underflow right here */
	outb_p(0x00, 0x43);	/* latch the count ASAP */

	count = inb_p(0x40);	/* read the latched count */

	/*
	 * We do this guaranteed double memory access instead of a _p 
	 * postfix in the previous port access. Wheee, hackady hack
	 */
 	jiffies_t = jiffies;

	count |= inb_p(0x40) << 8;

	/* Detect timer underflows.  If we haven't had a timer tick since 
	   the last time we were called, and time is apparently going
	   backwards, the counter must have wrapped during this routine. */
	if ((jiffies_t == jiffies_p) && (count > count_p))
		count -= (mSEC_10_from_14/6);
	else
		jiffies_p = jiffies_t;

	count_p = count;

	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);

	return count;
}

static irqreturn_t
65
isa_timer_interrupt(int irq, void *dev_id)
L
Linus Torvalds 已提交
66
{
67
	timer_tick();
L
Linus Torvalds 已提交
68 69 70 71 72 73
	return IRQ_HANDLED;
}

static struct irqaction isa_timer_irq = {
	.name		= "ISA timer tick",
	.handler	= isa_timer_interrupt,
B
Bernhard Walle 已提交
74
	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
};

static void __init isa_timer_init(void)
{
	/* enable PIT timer */
	/* set for periodic (4) and LSB/MSB write (0x30) */
	outb(0x34, 0x43);
	outb((mSEC_10_from_14/6) & 0xFF, 0x40);
	outb((mSEC_10_from_14/6) >> 8, 0x40);

	setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
}

struct sys_timer isa_timer = {
	.init		= isa_timer_init,
	.offset		= isa_gettimeoffset,
};