Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/allwinner/timer.c
Show All 34 Lines | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/timeet.h> | #include <sys/timeet.h> | ||||
#include <sys/timetc.h> | #include <sys/timetc.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/machdep.h> | |||||
#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> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
static u_int a10_timer_get_timecount(struct timecounter *); | static u_int a10_timer_get_timecount(struct timecounter *); | ||||
static int a10_timer_timer_start(struct eventtimer *, | static int a10_timer_timer_start(struct eventtimer *, | ||||
sbintime_t first, sbintime_t period); | sbintime_t first, sbintime_t period); | ||||
static int a10_timer_timer_stop(struct eventtimer *); | static int a10_timer_timer_stop(struct eventtimer *); | ||||
static uint64_t timer_read_counter64(void); | static uint64_t timer_read_counter64(void); | ||||
static int a10_timer_initialized = 0; | |||||
static int a10_timer_hardclock(void *); | static int a10_timer_hardclock(void *); | ||||
static int a10_timer_probe(device_t); | static int a10_timer_probe(device_t); | ||||
static int a10_timer_attach(device_t); | static int a10_timer_attach(device_t); | ||||
static delay_func a10_timer_delay; | |||||
static struct timecounter a10_timer_timecounter = { | static struct timecounter a10_timer_timecounter = { | ||||
.tc_name = "a10_timer timer0", | .tc_name = "a10_timer timer0", | ||||
.tc_get_timecount = a10_timer_get_timecount, | .tc_get_timecount = a10_timer_get_timecount, | ||||
.tc_counter_mask = ~0u, | .tc_counter_mask = ~0u, | ||||
.tc_frequency = 0, | .tc_frequency = 0, | ||||
.tc_quality = 1000, | .tc_quality = 1000, | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | a10_timer_attach(device_t dev) | ||||
sc->et.et_quality = 1000; | sc->et.et_quality = 1000; | ||||
sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency; | sc->et.et_min_period = (0x00000005LLU << 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 = a10_timer_timer_start; | sc->et.et_start = a10_timer_timer_start; | ||||
sc->et.et_stop = a10_timer_timer_stop; | sc->et.et_stop = a10_timer_timer_stop; | ||||
sc->et.et_priv = sc; | sc->et.et_priv = sc; | ||||
et_register(&sc->et); | et_register(&sc->et); | ||||
if (device_get_unit(dev) == 0) | if (device_get_unit(dev) == 0) { | ||||
arm_set_delay(a10_timer_delay, sc); | |||||
a10_timer_sc = sc; | a10_timer_sc = sc; | ||||
} | |||||
a10_timer_timecounter.tc_frequency = sc->timer0_freq; | a10_timer_timecounter.tc_frequency = sc->timer0_freq; | ||||
tc_init(&a10_timer_timecounter); | tc_init(&a10_timer_timecounter); | ||||
if (bootverbose) { | if (bootverbose) { | ||||
device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz); | device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz); | ||||
device_printf(sc->sc_dev, "event timer clock frequency %u\n", | device_printf(sc->sc_dev, "event timer clock frequency %u\n", | ||||
sc->timer0_freq); | sc->timer0_freq); | ||||
device_printf(sc->sc_dev, "timecounter clock frequency %lld\n", | device_printf(sc->sc_dev, "timecounter clock frequency %lld\n", | ||||
a10_timer_timecounter.tc_frequency); | a10_timer_timecounter.tc_frequency); | ||||
} | } | ||||
a10_timer_initialized = 1; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
a10_timer_timer_start(struct eventtimer *et, sbintime_t first, | a10_timer_timer_start(struct eventtimer *et, sbintime_t first, | ||||
sbintime_t period) | sbintime_t period) | ||||
{ | { | ||||
struct a10_timer_softc *sc; | struct a10_timer_softc *sc; | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | static driver_t a10_timer_driver = { | ||||
sizeof(struct a10_timer_softc), | sizeof(struct a10_timer_softc), | ||||
}; | }; | ||||
static devclass_t a10_timer_devclass; | static devclass_t a10_timer_devclass; | ||||
EARLY_DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0, | EARLY_DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0, | ||||
BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); | BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); | ||||
void | static void | ||||
DELAY(int usec) | a10_timer_delay(int usec, void *arg) | ||||
{ | { | ||||
uint32_t counter; | struct a10_timer_softc *sc = arg; | ||||
uint64_t end, now; | uint64_t end, now; | ||||
if (!a10_timer_initialized) { | |||||
for (; usec > 0; usec--) | |||||
for (counter = 50; counter > 0; counter--) | |||||
cpufunc_nullop(); | |||||
return; | |||||
} | |||||
now = timer_read_counter64(); | now = timer_read_counter64(); | ||||
end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1); | end = now + (sc->timer0_freq / 1000000) * (usec + 1); | ||||
while (now < end) | while (now < end) | ||||
now = timer_read_counter64(); | now = timer_read_counter64(); | ||||
} | } | ||||