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