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