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 */ 7*4e8d7637SRussell King #include <linux/clockchips.h> 8*4e8d7637SRussell 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> 13*4e8d7637SRussell King #include <linux/timex.h> 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds #include <asm/irq.h> 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #include <asm/mach/time.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds #include "common.h" 201da177e4SLinus Torvalds 21*4e8d7637SRussell King #define PIT_MODE 0x43 22*4e8d7637SRussell King #define PIT_CH0 0x40 231da177e4SLinus Torvalds 24*4e8d7637SRussell King #define PIT_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ) 25*4e8d7637SRussell King 26*4e8d7637SRussell King static cycle_t pit_read(struct clocksource *cs) 271da177e4SLinus Torvalds { 28*4e8d7637SRussell King unsigned long flags; 29*4e8d7637SRussell King static int old_count; 30*4e8d7637SRussell King static u32 old_jifs; 311da177e4SLinus Torvalds int count; 32*4e8d7637SRussell King u32 jifs; 331da177e4SLinus Torvalds 34*4e8d7637SRussell King raw_local_irq_save(flags); 351da177e4SLinus Torvalds 36*4e8d7637SRussell King jifs = jiffies; 37*4e8d7637SRussell King outb_p(0x00, PIT_MODE); /* latch the count */ 38*4e8d7637SRussell King count = inb_p(PIT_CH0); /* read the latched count */ 39*4e8d7637SRussell King count |= inb_p(PIT_CH0) << 8; 401da177e4SLinus Torvalds 41*4e8d7637SRussell King if (count > old_count && jifs == old_jifs) 42*4e8d7637SRussell King count = old_count; 431da177e4SLinus Torvalds 44*4e8d7637SRussell King old_count = count; 45*4e8d7637SRussell King old_jifs = jifs; 461da177e4SLinus Torvalds 47*4e8d7637SRussell King raw_local_irq_restore(flags); 481da177e4SLinus Torvalds 49*4e8d7637SRussell King count = (PIT_LATCH - 1) - count; 501da177e4SLinus Torvalds 51*4e8d7637SRussell King return (cycle_t)(jifs * PIT_LATCH) + count; 521da177e4SLinus Torvalds } 531da177e4SLinus Torvalds 54*4e8d7637SRussell King static struct clocksource pit_cs = { 55*4e8d7637SRussell King .name = "pit", 56*4e8d7637SRussell King .rating = 110, 57*4e8d7637SRussell King .read = pit_read, 58*4e8d7637SRussell King .mask = CLOCKSOURCE_MASK(32), 59*4e8d7637SRussell King }; 60*4e8d7637SRussell King 61*4e8d7637SRussell King static void pit_set_mode(enum clock_event_mode mode, 62*4e8d7637SRussell King struct clock_event_device *evt) 631da177e4SLinus Torvalds { 64*4e8d7637SRussell King unsigned long flags; 65*4e8d7637SRussell King 66*4e8d7637SRussell King raw_local_irq_save(flags); 67*4e8d7637SRussell King 68*4e8d7637SRussell King switch (mode) { 69*4e8d7637SRussell King case CLOCK_EVT_MODE_PERIODIC: 70*4e8d7637SRussell King outb_p(0x34, PIT_MODE); 71*4e8d7637SRussell King outb_p(PIT_LATCH & 0xff, PIT_CH0); 72*4e8d7637SRussell King outb_p(PIT_LATCH >> 8, PIT_CH0); 73*4e8d7637SRussell King break; 74*4e8d7637SRussell King 75*4e8d7637SRussell King case CLOCK_EVT_MODE_SHUTDOWN: 76*4e8d7637SRussell King case CLOCK_EVT_MODE_UNUSED: 77*4e8d7637SRussell King outb_p(0x30, PIT_MODE); 78*4e8d7637SRussell King outb_p(0, PIT_CH0); 79*4e8d7637SRussell King outb_p(0, PIT_CH0); 80*4e8d7637SRussell King break; 81*4e8d7637SRussell King 82*4e8d7637SRussell King case CLOCK_EVT_MODE_ONESHOT: 83*4e8d7637SRussell King case CLOCK_EVT_MODE_RESUME: 84*4e8d7637SRussell King break; 85*4e8d7637SRussell King } 86*4e8d7637SRussell King local_irq_restore(flags); 87*4e8d7637SRussell King } 88*4e8d7637SRussell King 89*4e8d7637SRussell King static int pit_set_next_event(unsigned long delta, 90*4e8d7637SRussell King struct clock_event_device *evt) 91*4e8d7637SRussell King { 92*4e8d7637SRussell King return 0; 93*4e8d7637SRussell King } 94*4e8d7637SRussell King 95*4e8d7637SRussell King static struct clock_event_device pit_ce = { 96*4e8d7637SRussell King .name = "pit", 97*4e8d7637SRussell King .features = CLOCK_EVT_FEAT_PERIODIC, 98*4e8d7637SRussell King .set_mode = pit_set_mode, 99*4e8d7637SRussell King .set_next_event = pit_set_next_event, 100*4e8d7637SRussell King .shift = 32, 101*4e8d7637SRussell King }; 102*4e8d7637SRussell King 103*4e8d7637SRussell King static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) 104*4e8d7637SRussell King { 105*4e8d7637SRussell King struct clock_event_device *ce = dev_id; 106*4e8d7637SRussell King ce->event_handler(ce); 1071da177e4SLinus Torvalds return IRQ_HANDLED; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds 110*4e8d7637SRussell King static struct irqaction pit_timer_irq = { 111*4e8d7637SRussell King .name = "pit", 112*4e8d7637SRussell King .handler = pit_timer_interrupt, 113b30fabadSBernhard Walle .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 114*4e8d7637SRussell King .dev_id = &pit_ce, 1151da177e4SLinus Torvalds }; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds static void __init isa_timer_init(void) 1181da177e4SLinus Torvalds { 119*4e8d7637SRussell King pit_ce.cpumask = cpumask_of(smp_processor_id()); 120*4e8d7637SRussell King pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift); 121*4e8d7637SRussell King pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce); 122*4e8d7637SRussell King pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce); 1231da177e4SLinus Torvalds 124*4e8d7637SRussell King clocksource_register_hz(&pit_cs, PIT_TICK_RATE); 125*4e8d7637SRussell King 126*4e8d7637SRussell King setup_irq(pit_ce.irq, &pit_timer_irq); 127*4e8d7637SRussell King clockevents_register_device(&pit_ce); 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds struct sys_timer isa_timer = { 1311da177e4SLinus Torvalds .init = isa_timer_init, 1321da177e4SLinus Torvalds }; 133