1 High Precision Event Timer Driver for Linux
3 The High Precision Event Timer (HPET) hardware follows a specification
4 by Intel and Microsoft which can be found at
6 http://www.intel.com/hardwaredesign/hpetspec_1.pdf
8 Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
9 and up to 32 comparators. Normally three or more comparators are provided,
10 each of which can generate oneshot interrupts and at least one of which has
11 additional hardware to support periodic interrupts. The comparators are
12 also called "timers", which can be misleading since usually timers are
13 independent of each other ... these share a counter, complicating resets.
15 HPET devices can support two interrupt routing modes. In one mode, the
16 comparators are additional interrupt sources with no particular system
17 role. Many x86 BIOS writers don't route HPET interrupts at all, which
18 prevents use of that mode. They support the other "legacy replacement"
19 mode where the first two comparators block interrupts from 8254 timers
22 The driver supports detection of HPET driver allocation and initialization
23 of the HPET before the driver module_init routine is called. This enables
24 platform code which uses timer 0 or 1 as the main timer to intercept HPET
25 initialization. An example of this initialization can be found in
26 arch/x86/kernel/hpet.c.
28 The driver provides a userspace API which resembles the API found in the
29 RTC driver framework. An example user space program is provided below.
40 #include <sys/types.h>
46 #include <linux/hpet.h>
49 extern void hpet_open_close(int, const char **);
50 extern void hpet_info(int, const char **);
51 extern void hpet_poll(int, const char **);
52 extern void hpet_fasync(int, const char **);
53 extern void hpet_read(int, const char **);
56 #include <sys/ioctl.h>
61 void (*func)(int argc, const char ** argv);
82 main(int argc, const char ** argv)
90 fprintf(stderr, "-hpet: requires command\n");
95 for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
96 if (!strcmp(argv[0], hpet_command[i].command)) {
99 fprintf(stderr, "-hpet: executing %s\n",
100 hpet_command[i].command);
101 hpet_command[i].func(argc, argv);
105 fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
111 hpet_open_close(int argc, const char **argv)
116 fprintf(stderr, "hpet_open_close: device-name\n");
120 fd = open(argv[0], O_RDONLY);
122 fprintf(stderr, "hpet_open_close: open failed\n");
130 hpet_info(int argc, const char **argv)
135 hpet_poll(int argc, const char **argv)
138 int iterations, i, fd;
140 struct hpet_info info;
141 struct timeval stv, etv;
146 fprintf(stderr, "hpet_poll: device-name freq iterations\n");
150 freq = atoi(argv[1]);
151 iterations = atoi(argv[2]);
153 fd = open(argv[0], O_RDONLY);
156 fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
160 if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
161 fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
165 if (ioctl(fd, HPET_INFO, &info) < 0) {
166 fprintf(stderr, "hpet_poll: failed to get info\n");
170 fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
172 if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
173 fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
177 if (ioctl(fd, HPET_IE_ON, 0) < 0) {
178 fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
185 for (i = 0; i < iterations; i++) {
187 gettimeofday(&stv, &tz);
188 if (poll(&pfd, 1, -1) < 0)
189 fprintf(stderr, "hpet_poll: poll failed\n");
193 gettimeofday(&etv, &tz);
194 usec = stv.tv_sec * 1000000 + stv.tv_usec;
195 usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
198 "hpet_poll: expired time = 0x%lx\n", usec);
200 fprintf(stderr, "hpet_poll: revents = 0x%x\n",
203 if (read(fd, &data, sizeof(data)) != sizeof(data)) {
204 fprintf(stderr, "hpet_poll: read failed\n");
207 fprintf(stderr, "hpet_poll: data 0x%lx\n",
217 static int hpet_sigio_count;
222 fprintf(stderr, "hpet_sigio: called\n");
227 hpet_fasync(int argc, const char **argv)
230 int iterations, i, fd, value;
232 struct hpet_info info;
234 hpet_sigio_count = 0;
237 if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
238 fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
243 fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
247 fd = open(argv[0], O_RDONLY);
250 fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
255 if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
256 ((value = fcntl(fd, F_GETFL)) == 1) ||
257 (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
258 fprintf(stderr, "hpet_fasync: fcntl failed\n");
262 freq = atoi(argv[1]);
263 iterations = atoi(argv[2]);
265 if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
266 fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
270 if (ioctl(fd, HPET_INFO, &info) < 0) {
271 fprintf(stderr, "hpet_fasync: failed to get info\n");
275 fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
277 if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
278 fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
282 if (ioctl(fd, HPET_IE_ON, 0) < 0) {
283 fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
287 for (i = 0; i < iterations; i++) {
289 fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
293 signal(SIGIO, oldsig);