Home | History | Annotate | Line # | Download | only in ic
acpipmtimer.c revision 1.2
      1 /* $NetBSD: acpipmtimer.c,v 1.2 2007/08/27 06:17:28 xtraeme 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