Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/arm/generic_timer.c
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/vdso.h> | #include <sys/vdso.h> | ||||
#include <sys/watchdog.h> | #include <sys/watchdog.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#ifdef MULTIDELAY | |||||
#include <machine/machdep.h> /* For arm_set_delay */ | |||||
#endif | |||||
#ifdef FDT | #ifdef FDT | ||||
#include <dev/fdt/fdt_common.h> | #include <dev/fdt/fdt_common.h> | ||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#endif | #endif | ||||
#ifdef DEV_ACPI | #ifdef DEV_ACPI | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#define get_el0(x) READ_SPECIALREG(x ##_el0) | #define get_el0(x) READ_SPECIALREG(x ##_el0) | ||||
#define get_el1(x) READ_SPECIALREG(x ##_el1) | #define get_el1(x) READ_SPECIALREG(x ##_el1) | ||||
#define set_el0(x, val) WRITE_SPECIALREG(x ##_el0, val) | #define set_el0(x, val) WRITE_SPECIALREG(x ##_el0, val) | ||||
#define set_el1(x, val) WRITE_SPECIALREG(x ##_el1, val) | #define set_el1(x, val) WRITE_SPECIALREG(x ##_el1, val) | ||||
#endif | #endif | ||||
static uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, | static uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, | ||||
struct timecounter *tc); | struct timecounter *tc); | ||||
static void arm_tmr_do_delay(int usec, void *); | |||||
static int | static int | ||||
get_freq(void) | get_freq(void) | ||||
{ | { | ||||
return (get_el0(cntfrq)); | return (get_el0(cntfrq)); | ||||
} | } | ||||
static long | static long | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | #endif | ||||
sc->et.et_frequency = sc->clkfreq; | sc->et.et_frequency = sc->clkfreq; | ||||
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; | sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; | ||||
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; | sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; | ||||
sc->et.et_start = arm_tmr_start; | sc->et.et_start = arm_tmr_start; | ||||
sc->et.et_stop = arm_tmr_stop; | sc->et.et_stop = arm_tmr_stop; | ||||
sc->et.et_priv = sc; | sc->et.et_priv = sc; | ||||
et_register(&sc->et); | et_register(&sc->et); | ||||
#ifdef MULTIDELAY | |||||
arm_set_delay(arm_tmr_do_delay, sc); | |||||
#endif | |||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef FDT | #ifdef FDT | ||||
static device_method_t arm_tmr_fdt_methods[] = { | static device_method_t arm_tmr_fdt_methods[] = { | ||||
DEVMETHOD(device_probe, arm_tmr_fdt_probe), | DEVMETHOD(device_probe, arm_tmr_fdt_probe), | ||||
DEVMETHOD(device_attach, arm_tmr_attach), | DEVMETHOD(device_attach, arm_tmr_attach), | ||||
{ 0, 0 } | { 0, 0 } | ||||
Show All 28 Lines | |||||
}; | }; | ||||
static devclass_t arm_tmr_acpi_devclass; | static devclass_t arm_tmr_acpi_devclass; | ||||
EARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass, | EARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass, | ||||
0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); | 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); | ||||
#endif | #endif | ||||
void | static void | ||||
DELAY(int usec) | arm_tmr_do_delay(int usec, void *arg) | ||||
{ | { | ||||
struct arm_tmr_softc *sc = arg; | |||||
int32_t counts, counts_per_usec; | int32_t counts, counts_per_usec; | ||||
uint32_t first, last; | uint32_t first, last; | ||||
/* | |||||
* Check the timers are setup, if not just | |||||
* use a for loop for the meantime | |||||
*/ | |||||
if (arm_tmr_sc == NULL) { | |||||
for (; usec > 0; usec--) | |||||
for (counts = 200; counts > 0; counts--) | |||||
/* | |||||
* Prevent the compiler from optimizing | |||||
* out the loop | |||||
*/ | |||||
cpufunc_nullop(); | |||||
return; | |||||
} | |||||
/* Get the number of times to count */ | /* Get the number of times to count */ | ||||
counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1); | counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1); | ||||
/* | /* | ||||
* Clamp the timeout at a maximum value (about 32 seconds with | * Clamp the timeout at a maximum value (about 32 seconds with | ||||
* a 66MHz clock). *Nobody* should be delay()ing for anywhere | * a 66MHz clock). *Nobody* should be delay()ing for anywhere | ||||
* near that length of time and if they are, they should be hung | * near that length of time and if they are, they should be hung | ||||
* out to dry. | * out to dry. | ||||
*/ | */ | ||||
if (usec >= (0x80000000U / counts_per_usec)) | if (usec >= (0x80000000U / counts_per_usec)) | ||||
counts = (0x80000000U / counts_per_usec) - 1; | counts = (0x80000000U / counts_per_usec) - 1; | ||||
else | else | ||||
counts = usec * counts_per_usec; | counts = usec * counts_per_usec; | ||||
first = get_cntxct(arm_tmr_sc->physical); | first = get_cntxct(sc->physical); | ||||
while (counts > 0) { | while (counts > 0) { | ||||
last = get_cntxct(arm_tmr_sc->physical); | last = get_cntxct(sc->physical); | ||||
counts -= (int32_t)(last - first); | counts -= (int32_t)(last - first); | ||||
first = last; | first = last; | ||||
} | } | ||||
} | } | ||||
#ifndef MULTIDELAY | |||||
void | |||||
DELAY(int usec) | |||||
{ | |||||
int32_t counts; | |||||
/* | |||||
* Check the timers are setup, if not just | |||||
* use a for loop for the meantime | |||||
*/ | |||||
if (arm_tmr_sc == NULL) { | |||||
for (; usec > 0; usec--) | |||||
for (counts = 200; counts > 0; counts--) | |||||
/* | |||||
* Prevent the compiler from optimizing | |||||
* out the loop | |||||
*/ | |||||
cpufunc_nullop(); | |||||
} else | |||||
arm_tmr_do_delay(usec, arm_tmr_sc); | |||||
} | |||||
#endif | |||||
static uint32_t | static uint32_t | ||||
arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, | arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, | ||||
struct timecounter *tc) | struct timecounter *tc) | ||||
{ | { | ||||
vdso_th->th_physical = arm_tmr_sc->physical; | vdso_th->th_physical = arm_tmr_sc->physical; | ||||
bzero(vdso_th->th_res, sizeof(vdso_th->th_res)); | bzero(vdso_th->th_res, sizeof(vdso_th->th_res)); | ||||
return (tc == &arm_tmr_timecount); | return (tc == &arm_tmr_timecount); | ||||
} | } |