[dev][timer][arm_generic] Add arm64 support and select timer based on TIMER_ARM_GENERIC_SELECTED

TIMER_ARM_GENERIC_SELECTED can be set to CNTP, CNTPS or CNTV. CNTP is
used by default.

Change-Id: Idbce233062f244cee8245f48c6ad272111b7c58b
This commit is contained in:
Arve Hjønnevåg
2014-11-10 17:06:57 -08:00
parent eed6d25ef3
commit a17d19dae0

View File

@@ -35,6 +35,96 @@
#include <lib/fixed_point.h>
#if ARCH_ARM64
/* CNTFRQ AArch64 register */
#define TIMER_REG_CNTFRQ cntfrq_el0
/* CNTP AArch64 registers */
#define TIMER_REG_CNTP_CTL cntp_ctl_el0
#define TIMER_REG_CNTP_CVAL cntp_cval_el0
#define TIMER_REG_CNTP_TVAL cntp_tval_el0
#define TIMER_REG_CNTPCT cntpct_el0
/* CNTPS AArch64 registers */
#define TIMER_REG_CNTPS_CTL cntps_ctl_el1
#define TIMER_REG_CNTPS_CVAL cntps_cval_el1
#define TIMER_REG_CNTPS_TVAL cntps_tval_el1
#define TIMER_REG_CNTPSCT cntpct_el0
/* CNTV AArch64 registers */
#define TIMER_REG_CNTV_CTL cntv_ctl_el0
#define TIMER_REG_CNTV_CVAL cntv_cval_el0
#define TIMER_REG_CNTV_TVAL cntv_tval_el0
#define TIMER_REG_CNTVCT cntvct_el0
#define READ_TIMER_REG32(reg) ARM64_READ_SYSREG(reg)
#define READ_TIMER_REG64(reg) ARM64_READ_SYSREG(reg)
#define WRITE_TIMER_REG32(reg, val) ARM64_WRITE_SYSREG(reg, val)
#define WRITE_TIMER_REG64(reg, val) ARM64_WRITE_SYSREG(reg, val)
#else
/* CNTFRQ AArch32 register */
#define TIMER_REG_CNTFRQ "c0, 0"
/* CNTP AArch32 registers */
#define TIMER_REG_CNTP_CTL "c2, 1"
#define TIMER_REG_CNTP_CVAL "2"
#define TIMER_REG_CNTP_TVAL "c2, 0"
#define TIMER_REG_CNTPCT "0"
/* CNTPS AArch32 registers are banked and accessed though CNTP */
#define CNTPS CNTP
/* CNTV AArch32 registers */
#define TIMER_REG_CNTV_CTL "c3, 1"
#define TIMER_REG_CNTV_CVAL "3"
#define TIMER_REG_CNTV_TVAL "c3, 0"
#define TIMER_REG_CNTVCT "1"
#define READ_TIMER_REG32(reg) \
({ \
uint32_t _val; \
__asm__ volatile("mrc p15, 0, %0, c14, " reg : "=r" (_val)); \
_val; \
})
#define READ_TIMER_REG64(reg) \
({ \
uint64_t _val; \
__asm__ volatile("mrrc p15, " reg ", %0, %H0, c14" : "=r" (_val)); \
_val; \
})
#define WRITE_TIMER_REG32(reg, val) \
({ \
__asm__ volatile("mcr p15, 0, %0, c14, " reg :: "r" (val)); \
ISB; \
})
#define WRITE_TIMER_REG64(reg, val) \
({ \
__asm__ volatile("mcrr p15, " reg ", %0, %H0, c14" :: "r" (val)); \
ISB; \
})
#endif
#ifndef TIMER_ARM_GENERIC_SELECTED
#define TIMER_ARM_GENERIC_SELECTED CNTP
#endif
#define COMBINE3(a,b,c) a ## b ## c
#define XCOMBINE3(a,b,c) COMBINE3(a, b, c)
#define SELECTED_TIMER_REG(reg) XCOMBINE3(TIMER_REG_, TIMER_ARM_GENERIC_SELECTED, reg)
#define TIMER_REG_CTL SELECTED_TIMER_REG(_CTL)
#define TIMER_REG_CVAL SELECTED_TIMER_REG(_CVAL)
#define TIMER_REG_TVAL SELECTED_TIMER_REG(_TVAL)
#define TIMER_REG_CT SELECTED_TIMER_REG(CT)
static platform_timer_callback t_callback;
static int timer_irq;
@@ -61,7 +151,7 @@ static uint32_t read_cntfrq(void)
{
uint32_t cntfrq;
__asm__ volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (cntfrq));
cntfrq = READ_TIMER_REG32(TIMER_REG_CNTFRQ);
LTRACEF("cntfrq: 0x%08x, %u\n", cntfrq, cntfrq);
return cntfrq;
}
@@ -70,33 +160,33 @@ static uint32_t read_cntp_ctl(void)
{
uint32_t cntp_ctl;
__asm__ volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (cntp_ctl));
cntp_ctl = READ_TIMER_REG32(TIMER_REG_CTL);
return cntp_ctl;
}
static void write_cntp_ctl(uint32_t cntp_ctl)
{
LTRACEF_LEVEL(3, "cntp_ctl: 0x%x\n", cntp_ctl);
__asm__ volatile("mcr p15, 0, %0, c14, c2, 1" :: "r" (cntp_ctl));
LTRACEF_LEVEL(3, "cntp_ctl: 0x%x %x\n", cntp_ctl, read_cntp_ctl());
WRITE_TIMER_REG32(TIMER_REG_CTL, cntp_ctl);
}
static void write_cntp_cval(uint64_t cntp_cval)
{
LTRACEF_LEVEL(3, "cntp_cval: 0x%016llx, %llu\n", cntp_cval, cntp_cval);
__asm__ volatile("mcrr p15, 2, %0, %H0, c14" :: "r" (cntp_cval));
WRITE_TIMER_REG64(TIMER_REG_CVAL, cntp_cval);
}
static void write_cntp_tval(int32_t cntp_tval)
{
LTRACEF_LEVEL(3, "cntp_tval: 0x%08x, %d\n", cntp_tval, cntp_tval);
__asm__ volatile("mcr p15, 0, %0, c14, c2, 0" :: "r" (cntp_tval));
WRITE_TIMER_REG32(TIMER_REG_TVAL, cntp_tval);
}
static uint64_t read_cntpct(void)
{
uint64_t cntpct;
__asm__ volatile("mrrc p15, 0, %0, %H0, c14" : "=r" (cntpct));
cntpct = READ_TIMER_REG64(TIMER_REG_CT);
LTRACEF_LEVEL(3, "cntpct: 0x%016llx, %llu\n", cntpct, cntpct);
return cntpct;
}