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