Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/arm/generic_timer.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#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> | ||||
#if defined(__arm__) | #if defined(__arm__) | ||||
#include <machine/machdep.h> /* For arm_set_delay */ | #include <machine/machdep.h> /* For arm_set_delay */ | ||||
#endif | #endif | ||||
#if defined(__aarch64__) | |||||
#include <machine/vmm.h> /* For virt_enabled() */ | |||||
#endif | |||||
#ifdef FDT | #ifdef FDT | ||||
#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 | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
#endif | #endif | ||||
#include "generic_timer.h" | |||||
#define GT_CTRL_ENABLE (1 << 0) | #define GT_CTRL_ENABLE (1 << 0) | ||||
#define GT_CTRL_INT_MASK (1 << 1) | #define GT_CTRL_INT_MASK (1 << 1) | ||||
#define GT_CTRL_INT_STAT (1 << 2) | #define GT_CTRL_INT_STAT (1 << 2) | ||||
#define GT_REG_CTRL 0 | #define GT_REG_CTRL 0 | ||||
#define GT_REG_TVAL 1 | #define GT_REG_TVAL 1 | ||||
#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */ | #define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */ | ||||
#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */ | #define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */ | ||||
Show All 33 Lines | static struct timecounter arm_tmr_timecount = { | ||||
.tc_get_timecount = arm_tmr_get_timecount, | .tc_get_timecount = arm_tmr_get_timecount, | ||||
.tc_poll_pps = NULL, | .tc_poll_pps = NULL, | ||||
.tc_counter_mask = ~0u, | .tc_counter_mask = ~0u, | ||||
.tc_frequency = 0, | .tc_frequency = 0, | ||||
.tc_quality = 1000, | .tc_quality = 1000, | ||||
.tc_fill_vdso_timehands = arm_tmr_fill_vdso_timehands, | .tc_fill_vdso_timehands = arm_tmr_fill_vdso_timehands, | ||||
}; | }; | ||||
static device_t arm_tmr_dev; | |||||
#ifdef __arm__ | #ifdef __arm__ | ||||
#define get_el0(x) cp15_## x ##_get() | #define get_el0(x) cp15_## x ##_get() | ||||
#define get_el1(x) cp15_## x ##_get() | #define get_el1(x) cp15_## x ##_get() | ||||
#define set_el0(x, val) cp15_## x ##_set(val) | #define set_el0(x, val) cp15_## x ##_set(val) | ||||
#define set_el1(x, val) cp15_## x ##_set(val) | #define set_el1(x, val) cp15_## x ##_set(val) | ||||
#else /* __aarch64__ */ | #else /* __aarch64__ */ | ||||
#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) | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | arm_tmr_intr(void *arg) | ||||
} | } | ||||
if (sc->et.et_active) | if (sc->et.et_active) | ||||
sc->et.et_event_cb(&sc->et, sc->et.et_arg); | sc->et.et_event_cb(&sc->et, sc->et.et_arg); | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
int | |||||
arm_tmr_setup_intr(int gt_type, driver_filter_t filter, driver_intr_t handler, | |||||
void *arg) | |||||
{ | |||||
if (gt_type != GT_PHYS_SECURE && | |||||
gt_type != GT_PHYS_NONSECURE && | |||||
gt_type != GT_VIRT && | |||||
gt_type != GT_HYP) | |||||
return (ENXIO); | |||||
if (arm_tmr_sc->res[gt_type] == NULL) | |||||
return (ENXIO); | |||||
return (bus_setup_intr(arm_tmr_dev, arm_tmr_sc->res[gt_type], | |||||
INTR_TYPE_CLK, filter, handler, arg, &arm_tmr_sc->ihl[gt_type])); | |||||
} | |||||
int | |||||
arm_tmr_teardown_intr(int gt_type) | |||||
{ | |||||
if (gt_type != GT_PHYS_SECURE && | |||||
gt_type != GT_PHYS_NONSECURE && | |||||
gt_type != GT_VIRT && | |||||
gt_type != GT_HYP) | |||||
return (ENXIO); | |||||
if (arm_tmr_sc->res[gt_type] == NULL) | |||||
return (ENXIO); | |||||
return (bus_teardown_intr(arm_tmr_dev, arm_tmr_sc->res[gt_type], | |||||
arm_tmr_sc->ihl[gt_type])); | |||||
} | |||||
#ifdef FDT | #ifdef FDT | ||||
static int | static int | ||||
arm_tmr_fdt_probe(device_t dev) | arm_tmr_fdt_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
/* Otherwise set up the secure and non-secure physical timers. */ | /* Otherwise set up the secure and non-secure physical timers. */ | ||||
{ | { | ||||
sc->physical = true; | sc->physical = true; | ||||
first_timer = 0; | first_timer = 0; | ||||
last_timer = 1; | last_timer = 1; | ||||
} | } | ||||
#ifdef __aarch64__ | |||||
sc->physical |= virt_enabled(); | |||||
#endif | |||||
arm_tmr_sc = sc; | arm_tmr_sc = sc; | ||||
/* Setup secure, non-secure and virtual IRQs handler */ | /* Setup secure, non-secure and virtual IRQs handler */ | ||||
for (i = first_timer; i <= last_timer; i++) { | for (i = GT_PHYS_SECURE; i <= GT_VIRT; i++) { | ||||
/* If we do not have the interrupt, skip it. */ | /* If we do not have the interrupt, skip it. */ | ||||
if (sc->res[i] == NULL) | if (sc->res[i] == NULL) | ||||
continue; | continue; | ||||
#if defined(__aarch64__) | |||||
if (i == 2 && virt_enabled()) { | |||||
/* | |||||
* Do not install an interrupt handler for the virtual | |||||
* timer. This will be used by the VM. | |||||
*/ | |||||
continue; | |||||
} | |||||
#endif | |||||
error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, | error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, | ||||
arm_tmr_intr, NULL, sc, &sc->ihl[i]); | arm_tmr_intr, NULL, sc, &sc->ihl[i]); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "Unable to alloc int resource.\n"); | device_printf(dev, "Unable to alloc int resource.\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
} | } | ||||
/* Disable the virtual timer until we are ready */ | /* Disable the virtual timer until we are ready */ | ||||
if (sc->res[2] != NULL) | if (sc->res[2] != NULL) | ||||
arm_tmr_disable(false); | arm_tmr_disable(false); | ||||
/* And the physical */ | /* And the physical */ | ||||
if (sc->physical) | if (sc->physical) | ||||
arm_tmr_disable(true); | arm_tmr_disable(true); | ||||
arm_tmr_timecount.tc_frequency = sc->clkfreq; | arm_tmr_timecount.tc_frequency = sc->clkfreq; | ||||
Show All 9 Lines | #endif | ||||
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); | ||||
#if defined(__arm__) | #if defined(__arm__) | ||||
arm_set_delay(arm_tmr_do_delay, sc); | arm_set_delay(arm_tmr_do_delay, sc); | ||||
#endif | #endif | ||||
arm_tmr_dev = dev; | |||||
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), | ||||
▲ Show 20 Lines • Show All 102 Lines • Show Last 20 Lines |