xref: /openbmc/linux/samples/timers/hpet_example.c (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2155fe001SShuah Khan #include <stdio.h>
3155fe001SShuah Khan #include <stdlib.h>
4155fe001SShuah Khan #include <unistd.h>
5155fe001SShuah Khan #include <fcntl.h>
6155fe001SShuah Khan #include <string.h>
7155fe001SShuah Khan #include <memory.h>
8155fe001SShuah Khan #include <malloc.h>
9155fe001SShuah Khan #include <time.h>
10155fe001SShuah Khan #include <ctype.h>
11155fe001SShuah Khan #include <sys/types.h>
12155fe001SShuah Khan #include <sys/wait.h>
13155fe001SShuah Khan #include <signal.h>
14155fe001SShuah Khan #include <errno.h>
15155fe001SShuah Khan #include <sys/time.h>
16155fe001SShuah Khan #include <linux/hpet.h>
17155fe001SShuah Khan 
18155fe001SShuah Khan 
19155fe001SShuah Khan extern void hpet_open_close(int, const char **);
20155fe001SShuah Khan extern void hpet_info(int, const char **);
21155fe001SShuah Khan extern void hpet_poll(int, const char **);
22155fe001SShuah Khan extern void hpet_fasync(int, const char **);
23155fe001SShuah Khan extern void hpet_read(int, const char **);
24155fe001SShuah Khan 
25155fe001SShuah Khan #include <sys/poll.h>
26155fe001SShuah Khan #include <sys/ioctl.h>
27155fe001SShuah Khan 
28155fe001SShuah Khan struct hpet_command {
29155fe001SShuah Khan 	char		*command;
30155fe001SShuah Khan 	void		(*func)(int argc, const char ** argv);
31155fe001SShuah Khan } hpet_command[] = {
32155fe001SShuah Khan 	{
33155fe001SShuah Khan 		"open-close",
34155fe001SShuah Khan 		hpet_open_close
35155fe001SShuah Khan 	},
36155fe001SShuah Khan 	{
37155fe001SShuah Khan 		"info",
38155fe001SShuah Khan 		hpet_info
39155fe001SShuah Khan 	},
40155fe001SShuah Khan 	{
41155fe001SShuah Khan 		"poll",
42155fe001SShuah Khan 		hpet_poll
43155fe001SShuah Khan 	},
44155fe001SShuah Khan 	{
45155fe001SShuah Khan 		"fasync",
46155fe001SShuah Khan 		hpet_fasync
47155fe001SShuah Khan 	},
48155fe001SShuah Khan };
49155fe001SShuah Khan 
50155fe001SShuah Khan int
main(int argc,const char ** argv)51155fe001SShuah Khan main(int argc, const char ** argv)
52155fe001SShuah Khan {
53155fe001SShuah Khan 	unsigned int	i;
54155fe001SShuah Khan 
55155fe001SShuah Khan 	argc--;
56155fe001SShuah Khan 	argv++;
57155fe001SShuah Khan 
58155fe001SShuah Khan 	if (!argc) {
59155fe001SShuah Khan 		fprintf(stderr, "-hpet: requires command\n");
60155fe001SShuah Khan 		return -1;
61155fe001SShuah Khan 	}
62155fe001SShuah Khan 
63155fe001SShuah Khan 
64155fe001SShuah Khan 	for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
65155fe001SShuah Khan 		if (!strcmp(argv[0], hpet_command[i].command)) {
66155fe001SShuah Khan 			argc--;
67155fe001SShuah Khan 			argv++;
68155fe001SShuah Khan 			fprintf(stderr, "-hpet: executing %s\n",
69155fe001SShuah Khan 				hpet_command[i].command);
70155fe001SShuah Khan 			hpet_command[i].func(argc, argv);
71155fe001SShuah Khan 			return 0;
72155fe001SShuah Khan 		}
73155fe001SShuah Khan 
74155fe001SShuah Khan 	fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
75155fe001SShuah Khan 
76155fe001SShuah Khan 	return -1;
77155fe001SShuah Khan }
78155fe001SShuah Khan 
79155fe001SShuah Khan void
hpet_open_close(int argc,const char ** argv)80155fe001SShuah Khan hpet_open_close(int argc, const char **argv)
81155fe001SShuah Khan {
82155fe001SShuah Khan 	int	fd;
83155fe001SShuah Khan 
84155fe001SShuah Khan 	if (argc != 1) {
85155fe001SShuah Khan 		fprintf(stderr, "hpet_open_close: device-name\n");
86155fe001SShuah Khan 		return;
87155fe001SShuah Khan 	}
88155fe001SShuah Khan 
89155fe001SShuah Khan 	fd = open(argv[0], O_RDONLY);
90155fe001SShuah Khan 	if (fd < 0)
91155fe001SShuah Khan 		fprintf(stderr, "hpet_open_close: open failed\n");
92155fe001SShuah Khan 	else
93155fe001SShuah Khan 		close(fd);
94155fe001SShuah Khan 
95155fe001SShuah Khan 	return;
96155fe001SShuah Khan }
97155fe001SShuah Khan 
98155fe001SShuah Khan void
hpet_info(int argc,const char ** argv)99155fe001SShuah Khan hpet_info(int argc, const char **argv)
100155fe001SShuah Khan {
101155fe001SShuah Khan 	struct hpet_info	info;
102155fe001SShuah Khan 	int			fd;
103155fe001SShuah Khan 
104155fe001SShuah Khan 	if (argc != 1) {
105155fe001SShuah Khan 		fprintf(stderr, "hpet_info: device-name\n");
106155fe001SShuah Khan 		return;
107155fe001SShuah Khan 	}
108155fe001SShuah Khan 
109155fe001SShuah Khan 	fd = open(argv[0], O_RDONLY);
110155fe001SShuah Khan 	if (fd < 0) {
111155fe001SShuah Khan 		fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
112155fe001SShuah Khan 		return;
113155fe001SShuah Khan 	}
114155fe001SShuah Khan 
115155fe001SShuah Khan 	if (ioctl(fd, HPET_INFO, &info) < 0) {
116155fe001SShuah Khan 		fprintf(stderr, "hpet_info: failed to get info\n");
117155fe001SShuah Khan 		goto out;
118155fe001SShuah Khan 	}
119155fe001SShuah Khan 
120155fe001SShuah Khan 	fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
121155fe001SShuah Khan 		info.hi_ireqfreq, info.hi_flags);
122155fe001SShuah Khan 	fprintf(stderr, "hi_hpet %d hi_timer %d\n",
123155fe001SShuah Khan 		info.hi_hpet, info.hi_timer);
124155fe001SShuah Khan 
125155fe001SShuah Khan out:
126155fe001SShuah Khan 	close(fd);
127155fe001SShuah Khan 	return;
128155fe001SShuah Khan }
129155fe001SShuah Khan 
130155fe001SShuah Khan void
hpet_poll(int argc,const char ** argv)131155fe001SShuah Khan hpet_poll(int argc, const char **argv)
132155fe001SShuah Khan {
133155fe001SShuah Khan 	unsigned long		freq;
134155fe001SShuah Khan 	int			iterations, i, fd;
135155fe001SShuah Khan 	struct pollfd		pfd;
136155fe001SShuah Khan 	struct hpet_info	info;
137155fe001SShuah Khan 	struct timeval		stv, etv;
138155fe001SShuah Khan 	struct timezone		tz;
139155fe001SShuah Khan 	long			usec;
140155fe001SShuah Khan 
141155fe001SShuah Khan 	if (argc != 3) {
142155fe001SShuah Khan 		fprintf(stderr, "hpet_poll: device-name freq iterations\n");
143155fe001SShuah Khan 		return;
144155fe001SShuah Khan 	}
145155fe001SShuah Khan 
146155fe001SShuah Khan 	freq = atoi(argv[1]);
147155fe001SShuah Khan 	iterations = atoi(argv[2]);
148155fe001SShuah Khan 
149155fe001SShuah Khan 	fd = open(argv[0], O_RDONLY);
150155fe001SShuah Khan 
151155fe001SShuah Khan 	if (fd < 0) {
152155fe001SShuah Khan 		fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
153155fe001SShuah Khan 		return;
154155fe001SShuah Khan 	}
155155fe001SShuah Khan 
156155fe001SShuah Khan 	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
157155fe001SShuah Khan 		fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
158155fe001SShuah Khan 		goto out;
159155fe001SShuah Khan 	}
160155fe001SShuah Khan 
161155fe001SShuah Khan 	if (ioctl(fd, HPET_INFO, &info) < 0) {
162155fe001SShuah Khan 		fprintf(stderr, "hpet_poll: failed to get info\n");
163155fe001SShuah Khan 		goto out;
164155fe001SShuah Khan 	}
165155fe001SShuah Khan 
166155fe001SShuah Khan 	fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
167155fe001SShuah Khan 
168155fe001SShuah Khan 	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
169155fe001SShuah Khan 		fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
170155fe001SShuah Khan 		goto out;
171155fe001SShuah Khan 	}
172155fe001SShuah Khan 
173155fe001SShuah Khan 	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
174155fe001SShuah Khan 		fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
175155fe001SShuah Khan 		goto out;
176155fe001SShuah Khan 	}
177155fe001SShuah Khan 
178155fe001SShuah Khan 	pfd.fd = fd;
179155fe001SShuah Khan 	pfd.events = POLLIN;
180155fe001SShuah Khan 
181155fe001SShuah Khan 	for (i = 0; i < iterations; i++) {
182155fe001SShuah Khan 		pfd.revents = 0;
183155fe001SShuah Khan 		gettimeofday(&stv, &tz);
184155fe001SShuah Khan 		if (poll(&pfd, 1, -1) < 0)
185155fe001SShuah Khan 			fprintf(stderr, "hpet_poll: poll failed\n");
186155fe001SShuah Khan 		else {
187155fe001SShuah Khan 			long 	data;
188155fe001SShuah Khan 
189155fe001SShuah Khan 			gettimeofday(&etv, &tz);
190155fe001SShuah Khan 			usec = stv.tv_sec * 1000000 + stv.tv_usec;
191155fe001SShuah Khan 			usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
192155fe001SShuah Khan 
193155fe001SShuah Khan 			fprintf(stderr,
194155fe001SShuah Khan 				"hpet_poll: expired time = 0x%lx\n", usec);
195155fe001SShuah Khan 
196155fe001SShuah Khan 			fprintf(stderr, "hpet_poll: revents = 0x%x\n",
197155fe001SShuah Khan 				pfd.revents);
198155fe001SShuah Khan 
199155fe001SShuah Khan 			if (read(fd, &data, sizeof(data)) != sizeof(data)) {
200155fe001SShuah Khan 				fprintf(stderr, "hpet_poll: read failed\n");
201155fe001SShuah Khan 			}
202155fe001SShuah Khan 			else
203155fe001SShuah Khan 				fprintf(stderr, "hpet_poll: data 0x%lx\n",
204155fe001SShuah Khan 					data);
205155fe001SShuah Khan 		}
206155fe001SShuah Khan 	}
207155fe001SShuah Khan 
208155fe001SShuah Khan out:
209155fe001SShuah Khan 	close(fd);
210155fe001SShuah Khan 	return;
211155fe001SShuah Khan }
212155fe001SShuah Khan 
213155fe001SShuah Khan static int hpet_sigio_count;
214155fe001SShuah Khan 
215155fe001SShuah Khan static void
hpet_sigio(int val)216155fe001SShuah Khan hpet_sigio(int val)
217155fe001SShuah Khan {
218155fe001SShuah Khan 	fprintf(stderr, "hpet_sigio: called\n");
219155fe001SShuah Khan 	hpet_sigio_count++;
220155fe001SShuah Khan }
221155fe001SShuah Khan 
222155fe001SShuah Khan void
hpet_fasync(int argc,const char ** argv)223155fe001SShuah Khan hpet_fasync(int argc, const char **argv)
224155fe001SShuah Khan {
225155fe001SShuah Khan 	unsigned long		freq;
226155fe001SShuah Khan 	int			iterations, i, fd, value;
227155fe001SShuah Khan 	sig_t			oldsig;
228155fe001SShuah Khan 	struct hpet_info	info;
229155fe001SShuah Khan 
230155fe001SShuah Khan 	hpet_sigio_count = 0;
231155fe001SShuah Khan 	fd = -1;
232155fe001SShuah Khan 
233155fe001SShuah Khan 	if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
234155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
235155fe001SShuah Khan 		return;
236155fe001SShuah Khan 	}
237155fe001SShuah Khan 
238155fe001SShuah Khan 	if (argc != 3) {
239155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
240155fe001SShuah Khan 		goto out;
241155fe001SShuah Khan 	}
242155fe001SShuah Khan 
243155fe001SShuah Khan 	fd = open(argv[0], O_RDONLY);
244155fe001SShuah Khan 
245155fe001SShuah Khan 	if (fd < 0) {
246155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
247155fe001SShuah Khan 		return;
248155fe001SShuah Khan 	}
249155fe001SShuah Khan 
250155fe001SShuah Khan 
251155fe001SShuah Khan 	if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
252155fe001SShuah Khan 		((value = fcntl(fd, F_GETFL)) == 1) ||
253155fe001SShuah Khan 		(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
254155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: fcntl failed\n");
255155fe001SShuah Khan 		goto out;
256155fe001SShuah Khan 	}
257155fe001SShuah Khan 
258155fe001SShuah Khan 	freq = atoi(argv[1]);
259155fe001SShuah Khan 	iterations = atoi(argv[2]);
260155fe001SShuah Khan 
261155fe001SShuah Khan 	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
262155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
263155fe001SShuah Khan 		goto out;
264155fe001SShuah Khan 	}
265155fe001SShuah Khan 
266155fe001SShuah Khan 	if (ioctl(fd, HPET_INFO, &info) < 0) {
267155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: failed to get info\n");
268155fe001SShuah Khan 		goto out;
269155fe001SShuah Khan 	}
270155fe001SShuah Khan 
271155fe001SShuah Khan 	fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
272155fe001SShuah Khan 
273155fe001SShuah Khan 	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
274155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
275155fe001SShuah Khan 		goto out;
276155fe001SShuah Khan 	}
277155fe001SShuah Khan 
278155fe001SShuah Khan 	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
279155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
280155fe001SShuah Khan 		goto out;
281155fe001SShuah Khan 	}
282155fe001SShuah Khan 
283155fe001SShuah Khan 	for (i = 0; i < iterations; i++) {
284155fe001SShuah Khan 		(void) pause();
285155fe001SShuah Khan 		fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
286155fe001SShuah Khan 	}
287155fe001SShuah Khan 
288155fe001SShuah Khan out:
289155fe001SShuah Khan 	signal(SIGIO, oldsig);
290155fe001SShuah Khan 
291155fe001SShuah Khan 	if (fd >= 0)
292155fe001SShuah Khan 		close(fd);
293155fe001SShuah Khan 
294155fe001SShuah Khan 	return;
295155fe001SShuah Khan }
296