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