linux/drivers/clocksource/i8253.c
<<
>>
Prefs
   1/*
   2 * i8253 PIT clocksource
   3 */
   4#include <linux/clockchips.h>
   5#include <linux/init.h>
   6#include <linux/io.h>
   7#include <linux/spinlock.h>
   8#include <linux/timex.h>
   9#include <linux/module.h>
  10#include <linux/i8253.h>
  11#include <linux/smp.h>
  12
  13/*
  14 * Protects access to I/O ports
  15 *
  16 * 0040-0043 : timer0, i8253 / i8254
  17 * 0061-0061 : NMI Control Register which contains two speaker control bits.
  18 */
  19DEFINE_RAW_SPINLOCK(i8253_lock);
  20EXPORT_SYMBOL(i8253_lock);
  21
  22#ifdef CONFIG_CLKSRC_I8253
  23/*
  24 * Since the PIT overflows every tick, its not very useful
  25 * to just read by itself. So use jiffies to emulate a free
  26 * running counter:
  27 */
  28static cycle_t i8253_read(struct clocksource *cs)
  29{
  30        static int old_count;
  31        static u32 old_jifs;
  32        unsigned long flags;
  33        int count;
  34        u32 jifs;
  35
  36        raw_spin_lock_irqsave(&i8253_lock, flags);
  37        /*
  38         * Although our caller may have the read side of xtime_lock,
  39         * this is now a seqlock, and we are cheating in this routine
  40         * by having side effects on state that we cannot undo if
  41         * there is a collision on the seqlock and our caller has to
  42         * retry.  (Namely, old_jifs and old_count.)  So we must treat
  43         * jiffies as volatile despite the lock.  We read jiffies
  44         * before latching the timer count to guarantee that although
  45         * the jiffies value might be older than the count (that is,
  46         * the counter may underflow between the last point where
  47         * jiffies was incremented and the point where we latch the
  48         * count), it cannot be newer.
  49         */
  50        jifs = jiffies;
  51        outb_p(0x00, PIT_MODE); /* latch the count ASAP */
  52        count = inb_p(PIT_CH0); /* read the latched count */
  53        count |= inb_p(PIT_CH0) << 8;
  54
  55        /* VIA686a test code... reset the latch if count > max + 1 */
  56        if (count > PIT_LATCH) {
  57                outb_p(0x34, PIT_MODE);
  58                outb_p(PIT_LATCH & 0xff, PIT_CH0);
  59                outb_p(PIT_LATCH >> 8, PIT_CH0);
  60                count = PIT_LATCH - 1;
  61        }
  62
  63        /*
  64         * It's possible for count to appear to go the wrong way for a
  65         * couple of reasons:
  66         *
  67         *  1. The timer counter underflows, but we haven't handled the
  68         *     resulting interrupt and incremented jiffies yet.
  69         *  2. Hardware problem with the timer, not giving us continuous time,
  70         *     the counter does small "jumps" upwards on some Pentium systems,
  71         *     (see c't 95/10 page 335 for Neptun bug.)
  72         *
  73         * Previous attempts to handle these cases intelligently were
  74         * buggy, so we just do the simple thing now.
  75         */
  76        if (count > old_count && jifs == old_jifs)
  77                count = old_count;
  78
  79        old_count = count;
  80        old_jifs = jifs;
  81
  82        raw_spin_unlock_irqrestore(&i8253_lock, flags);
  83
  84        count = (PIT_LATCH - 1) - count;
  85
  86        return (cycle_t)(jifs * PIT_LATCH) + count;
  87}
  88
  89static struct clocksource i8253_cs = {
  90        .name           = "pit",
  91        .rating         = 110,
  92        .read           = i8253_read,
  93        .mask           = CLOCKSOURCE_MASK(32),
  94};
  95
  96int __init clocksource_i8253_init(void)
  97{
  98        return clocksource_register_hz(&i8253_cs, PIT_TICK_RATE);
  99}
 100#endif
 101
 102#ifdef CONFIG_CLKEVT_I8253
 103/*
 104 * Initialize the PIT timer.
 105 *
 106 * This is also called after resume to bring the PIT into operation again.
 107 */
 108static void init_pit_timer(enum clock_event_mode mode,
 109                           struct clock_event_device *evt)
 110{
 111        raw_spin_lock(&i8253_lock);
 112
 113        switch (mode) {
 114        case CLOCK_EVT_MODE_PERIODIC:
 115                /* binary, mode 2, LSB/MSB, ch 0 */
 116                outb_p(0x34, PIT_MODE);
 117                outb_p(PIT_LATCH & 0xff , PIT_CH0);     /* LSB */
 118                outb_p(PIT_LATCH >> 8 , PIT_CH0);               /* MSB */
 119                break;
 120
 121        case CLOCK_EVT_MODE_SHUTDOWN:
 122        case CLOCK_EVT_MODE_UNUSED:
 123                if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
 124                    evt->mode == CLOCK_EVT_MODE_ONESHOT) {
 125                        outb_p(0x30, PIT_MODE);
 126                        outb_p(0, PIT_CH0);
 127                        outb_p(0, PIT_CH0);
 128                }
 129                break;
 130
 131        case CLOCK_EVT_MODE_ONESHOT:
 132                /* One shot setup */
 133                outb_p(0x38, PIT_MODE);
 134                break;
 135
 136        case CLOCK_EVT_MODE_RESUME:
 137                /* Nothing to do here */
 138                break;
 139        }
 140        raw_spin_unlock(&i8253_lock);
 141}
 142
 143/*
 144 * Program the next event in oneshot mode
 145 *
 146 * Delta is given in PIT ticks
 147 */
 148static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
 149{
 150        raw_spin_lock(&i8253_lock);
 151        outb_p(delta & 0xff , PIT_CH0); /* LSB */
 152        outb_p(delta >> 8 , PIT_CH0);           /* MSB */
 153        raw_spin_unlock(&i8253_lock);
 154
 155        return 0;
 156}
 157
 158/*
 159 * On UP the PIT can serve all of the possible timer functions. On SMP systems
 160 * it can be solely used for the global tick.
 161 */
 162struct clock_event_device i8253_clockevent = {
 163        .name           = "pit",
 164        .features       = CLOCK_EVT_FEAT_PERIODIC,
 165        .set_mode       = init_pit_timer,
 166        .set_next_event = pit_next_event,
 167};
 168
 169/*
 170 * Initialize the conversion factor and the min/max deltas of the clock event
 171 * structure and register the clock event source with the framework.
 172 */
 173void __init clockevent_i8253_init(bool oneshot)
 174{
 175        if (oneshot)
 176                i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT;
 177        /*
 178         * Start pit with the boot cpu mask. x86 might make it global
 179         * when it is used as broadcast device later.
 180         */
 181        i8253_clockevent.cpumask = cpumask_of(smp_processor_id());
 182
 183        clockevents_config_and_register(&i8253_clockevent, PIT_TICK_RATE,
 184                                        0xF, 0x7FFF);
 185}
 186#endif
 187
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.