blob: 3d8607b3cb43ff66193d959f483e9a0f9612284b [file] [log] [blame]
Jordan Crousef6145c32008-03-19 23:56:58 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
Uwe Hermann31538632008-08-31 22:10:35 +000030/**
31 * @file i386/timer.c
32 * i386 specific timer routines
Jordan Crouseb7461782008-08-28 23:12:22 +000033 */
34
Jordan Crousef6145c32008-03-19 23:56:58 +000035#include <libpayload.h>
36#include <arch/rdtsc.h>
37
Jordan Crouseb7461782008-08-28 23:12:22 +000038/**
39 * @ingroup arch
Uwe Hermann31538632008-08-31 22:10:35 +000040 * Global variable containing the speed of the processor in KHz.
Jordan Crouseb7461782008-08-28 23:12:22 +000041 */
Jordan Crouse48392662008-08-28 23:12:02 +000042u32 cpu_khz;
Jordan Crousef6145c32008-03-19 23:56:58 +000043
Uwe Hermann6a441bf2008-03-20 19:54:59 +000044/**
45 * Calculate the speed of the processor for use in delays.
46 *
47 * @return The CPU speed in kHz.
48 */
Uwe Hermanndc69e052008-03-20 01:53:30 +000049unsigned int get_cpu_speed(void)
Jordan Crousef6145c32008-03-19 23:56:58 +000050{
51 unsigned long long start, end;
52
Uwe Hermann6a441bf2008-03-20 19:54:59 +000053 /* Set up the PPC port - disable the speaker, enable the T2 gate. */
Jordan Crousef6145c32008-03-19 23:56:58 +000054 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
55
Uwe Hermann6a441bf2008-03-20 19:54:59 +000056 /* Set the PIT to Mode 0, counter 2, word access. */
Jordan Crousef6145c32008-03-19 23:56:58 +000057 outb(0xB0, 0x43);
58
Uwe Hermann6a441bf2008-03-20 19:54:59 +000059 /* Load the counter with 0xffff. */
60 outb(0xff, 0x42);
61 outb(0xff, 0x42);
Jordan Crousef6145c32008-03-19 23:56:58 +000062
Uwe Hermann6a441bf2008-03-20 19:54:59 +000063 /* Read the number of ticks during the period. */
Jordan Crousef6145c32008-03-19 23:56:58 +000064 start = rdtsc();
Uwe Hermann6a441bf2008-03-20 19:54:59 +000065 while (!(inb(0x61) & 0x20)) ;
Jordan Crousef6145c32008-03-19 23:56:58 +000066 end = rdtsc();
67
Uwe Hermann6a441bf2008-03-20 19:54:59 +000068 /*
Uwe Hermann661e3802008-03-21 18:37:23 +000069 * The clock rate is 1193180 Hz, the number of milliseconds for a
Uwe Hermann6a441bf2008-03-20 19:54:59 +000070 * period of 0xffff is 1193180 / (0xFFFF * 1000) or .0182.
71 * Multiply that by the number of measured clocks to get the kHz value.
72 */
73 cpu_khz = (unsigned int)((end - start) * 1193180U / (1000 * 0xffff));
Uwe Hermann14a3feb2008-03-20 20:46:44 +000074
75 return cpu_khz;
Jordan Crousef6145c32008-03-19 23:56:58 +000076}
77
Jordan Crousef2433a92008-10-20 17:08:08 +000078static inline void _delay(unsigned long long delta)
Jordan Crousef6145c32008-03-19 23:56:58 +000079{
80 unsigned long long timeout = rdtsc() + delta;
Uwe Hermann6a441bf2008-03-20 19:54:59 +000081 while (rdtsc() < timeout) ;
Jordan Crousef6145c32008-03-19 23:56:58 +000082}
83
Jordan Crouseb7461782008-08-28 23:12:22 +000084/**
Uwe Hermann31538632008-08-31 22:10:35 +000085 * Delay for a specified number of nanoseconds.
86 *
87 * @param n Number of nanoseconds to delay for.
Jordan Crouseb7461782008-08-28 23:12:22 +000088 */
Jordan Crousef6145c32008-03-19 23:56:58 +000089void ndelay(unsigned int n)
90{
Uwe Hermann6a441bf2008-03-20 19:54:59 +000091 _delay(n * cpu_khz / 1000000);
Jordan Crousef6145c32008-03-19 23:56:58 +000092}
93
Jordan Crouseb7461782008-08-28 23:12:22 +000094/**
Uwe Hermann31538632008-08-31 22:10:35 +000095 * Delay for a specified number of microseconds.
96 *
97 * @param n Number of microseconds to delay for.
Jordan Crouseb7461782008-08-28 23:12:22 +000098 */
Jordan Crouse234e87f2008-04-10 22:50:44 +000099void udelay(unsigned int n)
100{
101 _delay(n * cpu_khz / 1000);
102}
103
Jordan Crouseb7461782008-08-28 23:12:22 +0000104/**
Uwe Hermann31538632008-08-31 22:10:35 +0000105 * Delay for a specified number of milliseconds.
106 *
107 * @param m Number of milliseconds to delay for.
Jordan Crouseb7461782008-08-28 23:12:22 +0000108 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000109void mdelay(unsigned int m)
110{
111 _delay(m * cpu_khz);
112}
113
Jordan Crouseb7461782008-08-28 23:12:22 +0000114/**
Uwe Hermann31538632008-08-31 22:10:35 +0000115 * Delay for a specified number of seconds.
116 *
117 * @param s Number of seconds to delay for.
Jordan Crouseb7461782008-08-28 23:12:22 +0000118 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000119void delay(unsigned int s)
120{
121 _delay(s * cpu_khz * 1000);
122}