11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/arm/mach-footbridge/isa-timer.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 1998 Russell King.
51da177e4SLinus Torvalds  *  Copyright (C) 1998 Phil Blundell
61da177e4SLinus Torvalds  */
74e8d7637SRussell King #include <linux/clockchips.h>
84e8d7637SRussell King #include <linux/clocksource.h>
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/interrupt.h>
1155e86989SThomas Gleixner #include <linux/irq.h>
12fced80c7SRussell King #include <linux/io.h>
138c414ff3SRussell King #include <linux/spinlock.h>
144e8d7637SRussell King #include <linux/timex.h>
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <asm/irq.h>
178c414ff3SRussell King #include <asm/i8253.h>
181da177e4SLinus Torvalds #include <asm/mach/time.h>
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include "common.h"
211da177e4SLinus Torvalds 
228c414ff3SRussell King DEFINE_RAW_SPINLOCK(i8253_lock);
234e8d7637SRussell King 
244e8d7637SRussell King static void pit_set_mode(enum clock_event_mode mode,
254e8d7637SRussell King 	struct clock_event_device *evt)
261da177e4SLinus Torvalds {
274e8d7637SRussell King 	unsigned long flags;
284e8d7637SRussell King 
294e8d7637SRussell King 	raw_local_irq_save(flags);
304e8d7637SRussell King 
314e8d7637SRussell King 	switch (mode) {
324e8d7637SRussell King 	case CLOCK_EVT_MODE_PERIODIC:
334e8d7637SRussell King 		outb_p(0x34, PIT_MODE);
344e8d7637SRussell King 		outb_p(PIT_LATCH & 0xff, PIT_CH0);
354e8d7637SRussell King 		outb_p(PIT_LATCH >> 8, PIT_CH0);
364e8d7637SRussell King 		break;
374e8d7637SRussell King 
384e8d7637SRussell King 	case CLOCK_EVT_MODE_SHUTDOWN:
394e8d7637SRussell King 	case CLOCK_EVT_MODE_UNUSED:
404e8d7637SRussell King 		outb_p(0x30, PIT_MODE);
414e8d7637SRussell King 		outb_p(0, PIT_CH0);
424e8d7637SRussell King 		outb_p(0, PIT_CH0);
434e8d7637SRussell King 		break;
444e8d7637SRussell King 
454e8d7637SRussell King 	case CLOCK_EVT_MODE_ONESHOT:
464e8d7637SRussell King 	case CLOCK_EVT_MODE_RESUME:
474e8d7637SRussell King 		break;
484e8d7637SRussell King 	}
494e8d7637SRussell King 	local_irq_restore(flags);
504e8d7637SRussell King }
514e8d7637SRussell King 
524e8d7637SRussell King static int pit_set_next_event(unsigned long delta,
534e8d7637SRussell King 	struct clock_event_device *evt)
544e8d7637SRussell King {
554e8d7637SRussell King 	return 0;
564e8d7637SRussell King }
574e8d7637SRussell King 
584e8d7637SRussell King static struct clock_event_device pit_ce = {
594e8d7637SRussell King 	.name		= "pit",
604e8d7637SRussell King 	.features	= CLOCK_EVT_FEAT_PERIODIC,
614e8d7637SRussell King 	.set_mode	= pit_set_mode,
624e8d7637SRussell King 	.set_next_event	= pit_set_next_event,
634e8d7637SRussell King 	.shift		= 32,
644e8d7637SRussell King };
654e8d7637SRussell King 
664e8d7637SRussell King static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
674e8d7637SRussell King {
684e8d7637SRussell King 	struct clock_event_device *ce = dev_id;
694e8d7637SRussell King 	ce->event_handler(ce);
701da177e4SLinus Torvalds 	return IRQ_HANDLED;
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds 
734e8d7637SRussell King static struct irqaction pit_timer_irq = {
744e8d7637SRussell King 	.name		= "pit",
754e8d7637SRussell King 	.handler	= pit_timer_interrupt,
76b30fabadSBernhard Walle 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
774e8d7637SRussell King 	.dev_id		= &pit_ce,
781da177e4SLinus Torvalds };
791da177e4SLinus Torvalds 
801da177e4SLinus Torvalds static void __init isa_timer_init(void)
811da177e4SLinus Torvalds {
824e8d7637SRussell King 	pit_ce.cpumask = cpumask_of(smp_processor_id());
834e8d7637SRussell King 	pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
844e8d7637SRussell King 	pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
854e8d7637SRussell King 	pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
861da177e4SLinus Torvalds 
878c414ff3SRussell King 	clocksource_i8253_init();
884e8d7637SRussell King 
894e8d7637SRussell King 	setup_irq(pit_ce.irq, &pit_timer_irq);
904e8d7637SRussell King 	clockevents_register_device(&pit_ce);
911da177e4SLinus Torvalds }
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds struct sys_timer isa_timer = {
941da177e4SLinus Torvalds 	.init		= isa_timer_init,
951da177e4SLinus Torvalds };
96