First cut on an implementation of an ACPI power management counter
backend for timecounters. Due to known bugs in some chipsets, always read until we get 3 successive samples which are monotonic, as FreeBSD does in its "safe" variant. This can be refined later, either by chipset quirks or by a test (as FreeBSD does).
This commit is contained in:
parent
9b00231778
commit
c14d23ac86
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: acpi.c,v 1.89 2006/06/20 12:31:19 cube Exp $ */
|
||||
/* $NetBSD: acpi.c,v 1.90 2006/06/21 17:47:23 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -77,7 +77,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.89 2006/06/20 12:31:19 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.90 2006/06/21 17:47:23 drochner Exp $");
|
||||
|
||||
#include "opt_acpi.h"
|
||||
#include "opt_pcifixup.h"
|
||||
|
@ -94,6 +94,7 @@ __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.89 2006/06/20 12:31:19 cube Exp $");
|
|||
#include <dev/acpi/acpireg.h>
|
||||
#include <dev/acpi/acpivar.h>
|
||||
#include <dev/acpi/acpi_osd.h>
|
||||
#include <dev/acpi/acpi_timer.h>
|
||||
#ifdef ACPIVERBOSE
|
||||
#include <dev/acpi/acpidevs_data.h>
|
||||
#endif
|
||||
|
@ -351,6 +352,7 @@ acpi_attach(struct device *parent, struct device *self, void *aux)
|
|||
* Check for fixed-hardware features.
|
||||
*/
|
||||
acpi_enable_fixed_events(sc);
|
||||
acpitimer_init();
|
||||
|
||||
/*
|
||||
* Fix up PCI devices.
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* $NetBSD: acpi_timer.c,v 1.1 2006/06/21 17:47:23 drochner Exp $ */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __HAVE_TIMECOUNTER
|
||||
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <dev/acpi/acpica.h>
|
||||
#include <dev/acpi/acpi_timer.h>
|
||||
|
||||
static u_int acpitimer_read(struct timecounter *);
|
||||
|
||||
static struct timecounter acpi_timecounter = {
|
||||
acpitimer_read,
|
||||
0,
|
||||
0x00ffffff,
|
||||
PM_TIMER_FREQUENCY,
|
||||
"ACPI_PM_TMR",
|
||||
900
|
||||
};
|
||||
|
||||
int
|
||||
acpitimer_init()
|
||||
{
|
||||
uint32_t bits;
|
||||
ACPI_STATUS res;
|
||||
|
||||
res = AcpiGetTimerResolution(&bits);
|
||||
if (res != AE_OK)
|
||||
return (-1);
|
||||
|
||||
if (bits == 32)
|
||||
acpi_timecounter.tc_counter_mask = 0xffffffff;
|
||||
tc_init(&acpi_timecounter);
|
||||
|
||||
printf("acpitimer: %d bits\n", bits);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some chipsets (PIIX4 variants) do not latch correctly; there
|
||||
* is a chance that a transition is hit.
|
||||
* For now, just be conservative. We might detect the situation later
|
||||
* (by testing, or chipset quirks).
|
||||
*/
|
||||
static u_int
|
||||
acpitimer_read(struct timecounter *tc)
|
||||
{
|
||||
uint32_t t1, t2, t3;
|
||||
|
||||
AcpiGetTimer(&t2);
|
||||
AcpiGetTimer(&t3);
|
||||
do {
|
||||
t1 = t2;
|
||||
t2 = t3;
|
||||
AcpiGetTimer(&t3);
|
||||
} while ((t1 > t2) || (t2 > t3));
|
||||
return (t2);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
acpitimer_init()
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
/* $NetBSD: acpi_timer.h,v 1.1 2006/06/21 17:47:23 drochner Exp $ */
|
||||
|
||||
int acpitimer_init(void);
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.acpi,v 1.35 2006/01/31 09:30:06 kochi Exp $
|
||||
# $NetBSD: files.acpi,v 1.36 2006/06/21 17:47:23 drochner Exp $
|
||||
|
||||
include "dev/acpi/acpica/files.acpica"
|
||||
|
||||
|
@ -12,6 +12,7 @@ file dev/acpi/acpi_resource.c acpi
|
|||
file dev/acpi/acpi_powerres.c acpi
|
||||
file dev/acpi/acpi_madt.c acpi & mpacpi
|
||||
file dev/acpi/acpi_quirks.c acpi
|
||||
file dev/acpi/acpi_timer.c acpi
|
||||
|
||||
# ACPI Embedded Controller
|
||||
device acpiec
|
||||
|
|
Loading…
Reference in New Issue