Home | History | Annotate | Line # | Download | only in acpi
acpi_timer.c revision 1.1
      1 /* $NetBSD: acpi_timer.c,v 1.1 2006/06/21 17:47:23 drochner Exp $ */
      2 
      3 #include <sys/types.h>
      4 
      5 #ifdef __HAVE_TIMECOUNTER
      6 
      7 #include <sys/systm.h>
      8 #include <sys/time.h>
      9 #include <sys/timetc.h>
     10 #include <dev/acpi/acpica.h>
     11 #include <dev/acpi/acpi_timer.h>
     12 
     13 static u_int acpitimer_read(struct timecounter *);
     14 
     15 static struct timecounter acpi_timecounter = {
     16 	acpitimer_read,
     17 	0,
     18 	0x00ffffff,
     19 	PM_TIMER_FREQUENCY,
     20 	"ACPI_PM_TMR",
     21 	900
     22 };
     23 
     24 int
     25 acpitimer_init()
     26 {
     27 	uint32_t bits;
     28 	ACPI_STATUS res;
     29 
     30 	res = AcpiGetTimerResolution(&bits);
     31 	if (res != AE_OK)
     32 		return (-1);
     33 
     34 	if (bits == 32)
     35 		acpi_timecounter.tc_counter_mask = 0xffffffff;
     36 	tc_init(&acpi_timecounter);
     37 
     38 	printf("acpitimer: %d bits\n", bits);
     39 
     40 	return (0);
     41 }
     42 
     43 /*
     44  * Some chipsets (PIIX4 variants) do not latch correctly; there
     45  * is a chance that a transition is hit.
     46  * For now, just be conservative. We might detect the situation later
     47  * (by testing, or chipset quirks).
     48  */
     49 static u_int
     50 acpitimer_read(struct timecounter *tc)
     51 {
     52 	uint32_t t1, t2, t3;
     53 
     54 	AcpiGetTimer(&t2);
     55 	AcpiGetTimer(&t3);
     56 	do {
     57 		t1 = t2;
     58 		t2 = t3;
     59 		AcpiGetTimer(&t3);
     60 	} while ((t1 > t2) || (t2 > t3));
     61 	return (t2);
     62 }
     63 
     64 #else
     65 
     66 int
     67 acpitimer_init()
     68 {
     69 
     70 	return (0);
     71 }
     72 
     73 #endif
     74