uboot/cpu/i386/timer.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <asm/io.h>
  26#include <asm/i8254.h>
  27#include <asm/ibmpc.h>
  28
  29
  30static volatile unsigned long system_ticks;
  31static int timer_init_done =0;
  32
  33static void timer_isr(void *unused)
  34{
  35        system_ticks++;
  36}
  37
  38unsigned long get_system_ticks(void)
  39{
  40        return system_ticks;
  41}
  42
  43#define TIMER0_VALUE 0x04aa /* 1kHz 1.9318MHz / 1000 */
  44#define TIMER2_VALUE 0x0a8e /* 440Hz */
  45
  46int timer_init(void)
  47{
  48        system_ticks = 0;
  49
  50        irq_install_handler(0, timer_isr, NULL);
  51
  52        /* initialize timer 0 and 2
  53         *
  54         * Timer 0 is used to increment system_tick 1000 times/sec
  55         * Timer 1 was used for DRAM refresh in early PC's
  56         * Timer 2 is used to drive the speaker
  57         * (to stasrt a beep: write 3 to port 0x61,
  58         * to stop it again: write 0)
  59         */
  60
  61        outb(PIT_CMD_CTR0|PIT_CMD_BOTH|PIT_CMD_MODE2, PIT_BASE + PIT_COMMAND);
  62        outb(TIMER0_VALUE&0xff, PIT_BASE + PIT_T0);
  63        outb(TIMER0_VALUE>>8, PIT_BASE + PIT_T0);
  64
  65        outb(PIT_CMD_CTR2|PIT_CMD_BOTH|PIT_CMD_MODE3, PIT_BASE + PIT_COMMAND);
  66        outb(TIMER2_VALUE&0xff, PIT_BASE + PIT_T2);
  67        outb(TIMER2_VALUE>>8, PIT_BASE + PIT_T2);
  68
  69        timer_init_done = 1;
  70
  71        return 0;
  72}
  73
  74
  75#ifdef CONFIG_SYS_TIMER_GENERIC
  76
  77/* the unit for these is CONFIG_SYS_HZ */
  78
  79/* FixMe: implement these */
  80void reset_timer (void)
  81{
  82        system_ticks = 0;
  83}
  84
  85ulong get_timer (ulong base)
  86{
  87        return (system_ticks - base);
  88}
  89
  90void set_timer (ulong t)
  91{
  92        system_ticks = t;
  93}
  94
  95static u16 read_pit(void)
  96{
  97        u8 low;
  98        outb(PIT_CMD_LATCH, PIT_BASE + PIT_COMMAND);
  99        low = inb(PIT_BASE + PIT_T0);
 100        return ((inb(PIT_BASE + PIT_T0) << 8) | low);
 101}
 102
 103/* this is not very exact */
 104void udelay (unsigned long usec)
 105{
 106        int counter;
 107        int wraps;
 108
 109        if (!timer_init_done) {
 110                return;
 111        }
 112        counter = read_pit();
 113        wraps = usec/1000;
 114        usec = usec%1000;
 115
 116        usec*=1194;
 117        usec/=1000;
 118        usec+=counter;
 119        if (usec > 1194) {
 120                usec-=1194;
 121                wraps++;
 122        }
 123
 124        while (1) {
 125                int new_count = read_pit();
 126
 127                if (((new_count < usec) && !wraps) || wraps < 0) {
 128                        break;
 129                }
 130
 131                if (new_count > counter) {
 132                        wraps--;
 133                }
 134                counter = new_count;
 135        }
 136
 137}
 138
 139#if 0
 140/* this is a version with debug output */
 141void _udelay (unsigned long usec)
 142{
 143        int counter;
 144        int wraps;
 145
 146        int usec1, usec2, usec3;
 147        int wraps1, wraps2, wraps3, wraps4;
 148        int ctr1, ctr2, ctr3, nct1, nct2;
 149        int i;
 150        usec1=usec;
 151        if (!timer_init_done) {
 152                return;
 153        }
 154        counter = read_pit();
 155        ctr1 = counter;
 156        wraps = usec/1000;
 157        usec = usec%1000;
 158
 159        usec2 = usec;
 160        wraps1 = wraps;
 161
 162        usec*=1194;
 163        usec/=1000;
 164        usec+=counter;
 165        if (usec > 1194) {
 166                usec-=1194;
 167                wraps++;
 168        }
 169
 170        usec3 = usec;
 171        wraps2 = wraps;
 172
 173        ctr2 = wraps3 = nct1 = 4711;
 174        ctr3 = wraps4 = nct2 = 4711;
 175        i=0;
 176        while (1) {
 177                int new_count = read_pit();
 178                i++;
 179                if ((new_count < usec && !wraps) || wraps < 0) {
 180                        break;
 181                }
 182
 183                if (new_count > counter) {
 184                        wraps--;
 185                }
 186                if (ctr2==4711) {
 187                        ctr2 = counter;
 188                        wraps3 = wraps;
 189                        nct1 = new_count;
 190                } else {
 191                        ctr3 = counter;
 192                        wraps4 = wraps;
 193                        nct2 = new_count;
 194                }
 195
 196                counter = new_count;
 197        }
 198
 199        printf("udelay(%d)\n", usec1);
 200        printf("counter %d\n", ctr1);
 201        printf("1: wraps %d, usec %d\n", wraps1, usec2);
 202        printf("2: wraps %d, usec %d\n", wraps2, usec3);
 203        printf("new_count[0] %d counter %d wraps %d\n", nct1, ctr2, wraps3);
 204        printf("new_count[%d] %d counter %d wraps %d\n", i, nct2, ctr3, wraps4);
 205
 206        printf("%d %d %d %d %d\n",
 207               read_pit(), read_pit(), read_pit(),
 208               read_pit(), read_pit());
 209}
 210#endif
 211#endif
 212