summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_timer.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-04-30 05:27:01 +0000
committermarcel <marcel@FreeBSD.org>2003-04-30 05:27:01 +0000
commita9863cd5fe8315c179ae209cff29b7b9cfa09ceb (patch)
treef4b2dc162bf160d69f669672742689e2bcda5031 /sys/dev/acpica/acpi_timer.c
parentd05cdb70bf8634e72be28f9927f365b8467fb53c (diff)
downloadFreeBSD-src-a9863cd5fe8315c179ae209cff29b7b9cfa09ceb.zip
FreeBSD-src-a9863cd5fe8315c179ae209cff29b7b9cfa09ceb.tar.gz
o Don't announce that the timer is good when in fact it isn't timing
at all (ie reads yield constant values). Display the width as the difference between max and min so that constant timers have width zero. o Get the address of the timer from the XPmTmrBlk field instead of the V1_PmTmrBlk field. The former is a generic address and can specify a memory mapped I/O address. Remove <machine/bus_pio.h> to account for this. The timer is now properly configured on machines with ACPI v2 tables, whether PIO or MEMIO. Note that the acpica code converts v1 tables into v2 tables so the address is always present in XPmTmrBlk. o Replace the TIMER_READ macro with a call to the read_counter() function and add a barrier to make sure that we observe proper ordering of the reads.
Diffstat (limited to 'sys/dev/acpica/acpi_timer.c')
-rw-r--r--sys/dev/acpica/acpi_timer.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c
index a5a0dd6..67e308a 100644
--- a/sys/dev/acpica/acpi_timer.c
+++ b/sys/dev/acpica/acpi_timer.c
@@ -37,7 +37,6 @@
#include <sys/time.h>
#endif
-#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
@@ -61,9 +60,6 @@ ACPI_MODULE_NAME("TIMER")
static device_t acpi_timer_dev;
struct resource *acpi_timer_reg;
-#define TIMER_READ bus_space_read_4(rman_get_bustag(acpi_timer_reg), \
- rman_get_bushandle(acpi_timer_reg), \
- 0)
static u_int acpi_timer_frequency = 14318182/4;
@@ -75,6 +71,9 @@ static unsigned acpi_timer_get_timecount_safe(struct timecounter *tc);
static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS);
static void acpi_timer_test(void);
+static u_int32_t read_counter(void);
+static int test_counter(void);
+
/*
* Driver hung off ACPI.
*/
@@ -106,7 +105,20 @@ static struct timecounter acpi_timer_timecounter = {
"ACPI"
};
-static int test_counter(void);
+
+static u_int32_t
+read_counter()
+{
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst;
+ u_int32_t tv;
+
+ bsh = rman_get_bushandle(acpi_timer_reg);
+ bst = rman_get_bustag(acpi_timer_reg);
+ tv = bus_space_read_4(bst, bsh, 0);
+ bus_space_barrier(bst, bsh, 0, 4, BUS_SPACE_BARRIER_READ);
+ return (tv);
+}
#define N 2000
static int
@@ -117,9 +129,9 @@ test_counter()
min = 10000000;
max = 0;
- last = TIMER_READ;
+ last = read_counter();
for (n = 0; n < N; n++) {
- this = TIMER_READ;
+ this = read_counter();
delta = (this - last) & 0xffffff;
if (delta > max)
max = delta;
@@ -129,14 +141,14 @@ test_counter()
}
if (max - min > 2)
n = 0;
- else if (min < 0)
+ else if (min < 0 || max == 0)
n = 0;
else
n = 1;
if (bootverbose)
printf("ACPI timer looks %s min = %d, max = %d, width = %d\n",
n ? "GOOD" : "BAD ",
- min, max, max - min + 1);
+ min, max, max - min);
return (n);
}
@@ -149,7 +161,8 @@ acpi_timer_identify(driver_t *driver, device_t parent)
{
device_t dev;
char desc[40];
- int rid, i, j;
+ u_long rlen, rstart;
+ int i, j, rid, rtype;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -164,10 +177,17 @@ acpi_timer_identify(driver_t *driver, device_t parent)
return_VOID;
}
acpi_timer_dev = dev;
+
rid = 0;
- bus_set_resource(dev, SYS_RES_IOPORT, rid, AcpiGbl_FADT->V1_PmTmrBlk, sizeof(u_int32_t));
- if ((acpi_timer_reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE)) == NULL) {
- device_printf(dev, "couldn't allocate I/O resource (port 0x%x)\n", AcpiGbl_FADT->V1_PmTmrBlk);
+ rlen = AcpiGbl_FADT->PmTmLen;
+ rtype = (AcpiGbl_FADT->XPmTmrBlk.AddressSpaceId)
+ ? SYS_RES_IOPORT : SYS_RES_MEMORY;
+ rstart = AcpiGbl_FADT->XPmTmrBlk.Address;
+ bus_set_resource(dev, rtype, rid, rstart, rlen);
+ acpi_timer_reg = bus_alloc_resource(dev, rtype, &rid, 0, ~0, 1, RF_ACTIVE);
+ if (acpi_timer_reg == NULL) {
+ device_printf(dev, "couldn't allocate I/O resource (%s 0x%lx)\n",
+ (rtype == SYS_RES_IOPORT) ? "port" : "mem", rstart);
return_VOID;
}
if (testenv("debug.acpi.timer_test"))
@@ -186,7 +206,8 @@ acpi_timer_identify(driver_t *driver, device_t parent)
}
tc_init(&acpi_timer_timecounter);
- sprintf(desc, "%d-bit timer at 3.579545MHz", AcpiGbl_FADT->TmrValExt ? 32 : 24);
+ sprintf(desc, "%d-bit timer at 3.579545MHz", (AcpiGbl_FADT->TmrValExt)
+ ? 32 : 24);
device_set_desc_copy(dev, desc);
return_VOID;
@@ -212,7 +233,7 @@ acpi_timer_attach(device_t dev)
static unsigned
acpi_timer_get_timecount(struct timecounter *tc)
{
- return(TIMER_READ);
+ return (read_counter());
}
/*
@@ -224,12 +245,12 @@ acpi_timer_get_timecount_safe(struct timecounter *tc)
{
unsigned u1, u2, u3;
- u2 = TIMER_READ;
- u3 = TIMER_READ;
+ u2 = read_counter();
+ u3 = read_counter();
do {
u1 = u2;
u2 = u3;
- u3 = TIMER_READ;
+ u3 = read_counter();
} while (u1 > u2 || u2 > u3 || (u3 - u1) > 15);
return (u2);
}
@@ -266,9 +287,9 @@ acpi_timer_test(void)
{
u_int32_t u1, u2, u3;
- u1 = TIMER_READ;
- u2 = TIMER_READ;
- u3 = TIMER_READ;
+ u1 = read_counter();
+ u2 = read_counter();
+ u3 = read_counter();
device_printf(acpi_timer_dev, "timer test in progress, reboot to quit.\n");
for (;;) {
@@ -283,7 +304,7 @@ acpi_timer_test(void)
}
u1 = u2;
u2 = u3;
- u3 = TIMER_READ;
+ u3 = read_counter();
}
}
OpenPOWER on IntegriCloud