acpipmtimer.c revision 1.2 1 1.2 xtraeme /* $NetBSD: acpipmtimer.c,v 1.2 2007/08/27 06:17:28 xtraeme Exp $ */
2 1.1 drochner
3 1.1 drochner #include <sys/types.h>
4 1.1 drochner
5 1.1 drochner #ifdef __HAVE_TIMECOUNTER
6 1.1 drochner
7 1.1 drochner #include <sys/systm.h>
8 1.1 drochner #include <sys/device.h>
9 1.1 drochner #include <sys/malloc.h>
10 1.1 drochner #include <machine/bus.h>
11 1.1 drochner #include <sys/time.h>
12 1.1 drochner #include <sys/timetc.h>
13 1.1 drochner
14 1.1 drochner #include <dev/ic/acpipmtimer.h>
15 1.1 drochner
16 1.1 drochner #define ACPI_PM_TIMER_FREQUENCY 3579545
17 1.1 drochner
18 1.1 drochner struct hwtc {
19 1.1 drochner struct timecounter tc;
20 1.1 drochner bus_space_tag_t t;
21 1.1 drochner bus_space_handle_t h;
22 1.1 drochner bus_size_t off;
23 1.1 drochner };
24 1.1 drochner
25 1.1 drochner static u_int acpihwtimer_read_safe(struct timecounter *);
26 1.1 drochner static u_int acpihwtimer_read_fast(struct timecounter *);
27 1.1 drochner
28 1.1 drochner int
29 1.1 drochner acpipmtimer_attach(struct device *dev,
30 1.1 drochner bus_space_tag_t t, bus_space_handle_t h, bus_size_t off,
31 1.1 drochner int flags)
32 1.1 drochner {
33 1.1 drochner struct hwtc *tc;
34 1.1 drochner
35 1.1 drochner tc = malloc(sizeof(struct hwtc), M_DEVBUF, M_WAITOK|M_ZERO);
36 1.1 drochner if (!tc)
37 1.1 drochner return (-1);
38 1.1 drochner
39 1.1 drochner tc->tc.tc_name = dev->dv_xname;
40 1.1 drochner tc->tc.tc_frequency = ACPI_PM_TIMER_FREQUENCY;
41 1.1 drochner if (flags & ACPIPMT_32BIT)
42 1.1 drochner tc->tc.tc_counter_mask = 0xffffffff;
43 1.1 drochner else
44 1.1 drochner tc->tc.tc_counter_mask = 0x00ffffff;
45 1.1 drochner if (flags & ACPIPMT_BADLATCH) {
46 1.1 drochner tc->tc.tc_get_timecount = acpihwtimer_read_safe;
47 1.1 drochner tc->tc.tc_quality = 900;
48 1.1 drochner } else {
49 1.1 drochner tc->tc.tc_get_timecount = acpihwtimer_read_fast;
50 1.1 drochner tc->tc.tc_quality = 1000;
51 1.1 drochner }
52 1.1 drochner
53 1.1 drochner tc->t = t;
54 1.1 drochner tc->h = h;
55 1.1 drochner tc->off = off;
56 1.1 drochner
57 1.1 drochner tc->tc.tc_priv = tc;
58 1.1 drochner tc_init(&tc->tc);
59 1.2 xtraeme aprint_normal("%s: %d-bit timer\n", tc->tc.tc_name,
60 1.1 drochner (flags & ACPIPMT_32BIT ? 32 : 24));
61 1.1 drochner return (0);
62 1.1 drochner }
63 1.1 drochner
64 1.1 drochner #define r(h) bus_space_read_4(h->t, h->h, h->off)
65 1.1 drochner
66 1.1 drochner static u_int
67 1.1 drochner acpihwtimer_read_safe(struct timecounter *tc)
68 1.1 drochner {
69 1.1 drochner struct hwtc *h = tc->tc_priv;
70 1.1 drochner uint32_t t1, t2, t3;
71 1.1 drochner
72 1.1 drochner t2 = r(h);
73 1.1 drochner t3 = r(h);
74 1.1 drochner do {
75 1.1 drochner t1 = t2;
76 1.1 drochner t2 = t3;
77 1.1 drochner t3 = r(h);
78 1.1 drochner } while ((t1 > t2) || (t2 > t3));
79 1.1 drochner return (t2);
80 1.1 drochner }
81 1.1 drochner
82 1.1 drochner static u_int
83 1.1 drochner acpihwtimer_read_fast(struct timecounter *tc)
84 1.1 drochner {
85 1.1 drochner struct hwtc *h = tc->tc_priv;
86 1.1 drochner
87 1.1 drochner return r(h);
88 1.1 drochner }
89 1.1 drochner
90 1.1 drochner #endif
91