From 7b309274e35d4cbfd3379afba34a38de909ec7dc Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 2 Apr 2015 12:56:06 +0000 Subject: [PATCH] Add the generic timer registers to sysreg.h and cpu-v6.h, and use the access functions in the generic timer driver. Differential Revision: https://reviews.freebsd.org/D2198 Sponsored by: The FreeBSD Foundation --- sys/arm/arm/generic_timer.c | 39 +++++++++--------------------- sys/arm/include/cpu-v6.h | 47 +++++++++++++++++++++++++++++++++++++ sys/arm/include/sysreg.h | 22 +++++++++++++++++ 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index a447353c46c2..a00cb304d7e7 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -105,12 +105,7 @@ static struct timecounter arm_tmr_timecount = { static int get_freq(void) { - uint32_t val; - - /* cntfrq */ - __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); - - return (val); + return (cp15_cntfrq_get()); } static long @@ -120,11 +115,9 @@ get_cntxct(bool physical) isb(); if (physical) - /* cntpct */ - __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val)); + val = cp15_cntpct_get(); else - /* cntvct */ - __asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (val)); + val = cp15_cntvct_get(); return (val); } @@ -134,13 +127,9 @@ set_ctrl(uint32_t val, bool physical) { if (physical) - /* cntp_ctl */ - __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : : - [val] "r" (val)); + cp15_cntp_ctl_set(val); else - /* cntv_ctl */ - __asm volatile("mcr p15, 0, %[val], c14, c3, 1" : : - [val] "r" (val)); + cp15_cntv_ctl_set(val); isb(); return (0); @@ -151,13 +140,9 @@ set_tval(uint32_t val, bool physical) { if (physical) - /* cntp_tval */ - __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : : - [val] "r" (val)); + cp15_cntp_tval_set(val); else - /* cntv_tval */ - __asm volatile("mcr p15, 0, %[val], c14, c3, 0" : : - [val] "r" (val)); + cp15_cntv_tval_set(val); isb(); return (0); @@ -169,11 +154,9 @@ get_ctrl(bool physical) uint32_t val; if (physical) - /* cntp_ctl */ - __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + val = cp15_cntp_ctl_get(); else - /* cntv_ctl */ - __asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); + val = cp15_cntv_ctl_get(); return (val); } @@ -183,10 +166,10 @@ disable_user_access(void) { uint32_t cntkctl; - __asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); + cntkctl = cp15_cntkctl_get(); cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN | GT_CNTKCTL_EVNTEN | GT_CNTKCTL_PL0VCTEN | GT_CNTKCTL_PL0PCTEN); - __asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); + cp15_cntkctl_set(cntkctl); isb(); } diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index a7f0b53e9a7b..6c226a344f28 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -54,6 +54,15 @@ fname(void) \ return(reg); \ } +#define _R64F0(fname, aname) \ +static __inline uint64_t \ +fname(void) \ +{ \ + uint64_t reg; \ + __asm __volatile("mrrc\t" _FX(aname): "=r" (reg)); \ + return(reg); \ +} + #define _WF0(fname, aname...) \ static __inline void \ fname(void) \ @@ -68,6 +77,13 @@ fname(register_t reg) \ __asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \ } +#define _W64F1(fname, aname...) \ +static __inline void \ +fname(uint64_t reg) \ +{ \ + __asm __volatile("mcrr\t" _FX(aname):: "r" (reg)); \ +} + /* * Raw CP15 maintenance operations * !!! not for external use !!! @@ -189,6 +205,37 @@ _WF1(cp15_tpidruro_set, CP15_TPIDRURO(%0)) _RF0(cp15_tpidrpwr_get, CP15_TPIDRPRW(%0)) _WF1(cp15_tpidrpwr_set, CP15_TPIDRPRW(%0)) +/* Generic Timer registers - only use when you know the hardware is available */ +_RF0(cp15_cntfrq_get, CP15_CNTFRQ(%0)) +_WF1(cp15_cntfrq_set, CP15_CNTFRQ(%0)) +_RF0(cp15_cntkctl_get, CP15_CNTKCTL(%0)) +_WF1(cp15_cntkctl_set, CP15_CNTKCTL(%0)) +_RF0(cp15_cntp_tval_get, CP15_CNTP_TVAL(%0)) +_WF1(cp15_cntp_tval_set, CP15_CNTP_TVAL(%0)) +_RF0(cp15_cntp_ctl_get, CP15_CNTP_CTL(%0)) +_WF1(cp15_cntp_ctl_set, CP15_CNTP_CTL(%0)) +_RF0(cp15_cntv_tval_get, CP15_CNTV_TVAL(%0)) +_WF1(cp15_cntv_tval_set, CP15_CNTV_TVAL(%0)) +_RF0(cp15_cntv_ctl_get, CP15_CNTV_CTL(%0)) +_WF1(cp15_cntv_ctl_set, CP15_CNTV_CTL(%0)) +_RF0(cp15_cnthctl_get, CP15_CNTHCTL(%0)) +_WF1(cp15_cnthctl_set, CP15_CNTHCTL(%0)) +_RF0(cp15_cnthp_tval_get, CP15_CNTHP_TVAL(%0)) +_WF1(cp15_cnthp_tval_set, CP15_CNTHP_TVAL(%0)) +_RF0(cp15_cnthp_ctl_get, CP15_CNTHP_CTL(%0)) +_WF1(cp15_cnthp_ctl_set, CP15_CNTHP_CTL(%0)) + +_R64F0(cp15_cntpct_get, CP15_CNTPCT(%Q0, %R0)) +_R64F0(cp15_cntvct_get, CP15_CNTVCT(%Q0, %R0)) +_R64F0(cp15_cntp_cval_get, CP15_CNTP_CVAL(%Q0, %R0)) +_W64F1(cp15_cntp_cval_set, CP15_CNTP_CVAL(%Q0, %R0)) +_R64F0(cp15_cntv_cval_get, CP15_CNTV_CVAL(%Q0, %R0)) +_W64F1(cp15_cntv_cval_set, CP15_CNTV_CVAL(%Q0, %R0)) +_R64F0(cp15_cntvoff_get, CP15_CNTVOFF(%Q0, %R0)) +_W64F1(cp15_cntvoff_set, CP15_CNTVOFF(%Q0, %R0)) +_R64F0(cp15_cnthp_cval_get, CP15_CNTHP_CVAL(%Q0, %R0)) +_W64F1(cp15_cnthp_cval_set, CP15_CNTHP_CVAL(%Q0, %R0)) + #undef _FX #undef _RF0 #undef _WF0 diff --git a/sys/arm/include/sysreg.h b/sys/arm/include/sysreg.h index 7eec7272f68c..f29991ade8bd 100644 --- a/sys/arm/include/sysreg.h +++ b/sys/arm/include/sysreg.h @@ -256,6 +256,28 @@ #define CP15_TPIDRURO(rr) p15, 0, rr, c13, c0, 3 /* User Read-Only Thread ID Register */ #define CP15_TPIDRPRW(rr) p15, 0, rr, c13, c0, 4 /* PL1 only Thread ID Register */ +/* + * CP15 C14 registers + * These are the Generic Timer registers and may be unallocated on some SoCs. + * Only use these when you know the Generic Timer is available. + */ +#define CP15_CNTFRQ(rr) p15, 0, rr, c14, c0, 0 /* Counter Frequency Register */ +#define CP15_CNTKCTL(rr) p15, 0, rr, c14, c1, 0 /* Timer PL1 Control Register */ +#define CP15_CNTP_TVAL(rr) p15, 0, rr, c14, c2, 0 /* PL1 Physical Timer Value Register */ +#define CP15_CNTP_CTL(rr) p15, 0, rr, c14, c2, 1 /* PL1 Physical Timer Control Register */ +#define CP15_CNTV_TVAL(rr) p15, 0, rr, c14, c3, 0 /* Virtual Timer Value Register */ +#define CP15_CNTV_CTL(rr) p15, 0, rr, c14, c3, 1 /* Virtual Timer Control Register */ +#define CP15_CNTHCTL(rr) p15, 4, rr, c14, c1, 0 /* Timer PL2 Control Register */ +#define CP15_CNTHP_TVAL(rr) p15, 4, rr, c14, c2, 0 /* PL2 Physical Timer Value Register */ +#define CP15_CNTHP_CTL(rr) p15, 4, rr, c14, c2, 1 /* PL2 Physical Timer Control Register */ +/* 64-bit registers for use with mcrr/mrrc */ +#define CP15_CNTPCT(rq, rr) p15, 0, rq, rr, c14 /* Physical Count Register */ +#define CP15_CNTVCT(rq, rr) p15, 1, rq, rr, c14 /* Virtual Count Register */ +#define CP15_CNTP_CVAL(rq, rr) p15, 2, rq, rr, c14 /* PL1 Physical Timer Compare Value Register */ +#define CP15_CNTV_CVAL(rq, rr) p15, 3, rq, rr, c14 /* Virtual Timer Compare Value Register */ +#define CP15_CNTVOFF(rq, rr) p15, 4, rq, rr, c14 /* Virtual Offset Register */ +#define CP15_CNTHP_CVAL(rq, rr) p15, 6, rq, rr, c14 /* PL2 Physical Timer Compare Value Register */ + /* * CP15 C15 registers */