#include "serial.h"
#include "kernel/proc.h"
#include "kernel/debug.h"
+#include "omap_ccnt.h"
#include "glo.h"
void arch_init(void)
{
+ u32_t value;
+
k_stacks = (void*) &k_stacks_start;
assert(!((vir_bytes) k_stacks % K_STACK_SIZE));
#endif
ser_init();
+
+ /* enable user space access to cycle counter */
+ /* set cycle counter to 0: ARM ARM B4.1.113 and B4.1.117 */
+ asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r" (value));
+ value |= OMAP_PMCR_C; /* Reset counter */
+ value |= OMAP_PMCR_E; /* Enable counter hardware */
+ asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n": : "r" (value));
+
+ /* enable CCNT counting: ARM ARM B4.1.116 */
+ value = OMAP_PMCNTENSET_C; /* Enable PMCCNTR cycle counter */
+ asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n": : "r" (value));
+
+ /* enable cycle counter in user mode: ARM ARM B4.1.124 */
+ value = OMAP_PMUSERENR_EN;
+ asm volatile ("MCR p15, 0, %0, c9, c14, 0\t\n": : "r" (value));
}
/*===========================================================================*
--- /dev/null
+#ifndef _OMAP_CCNT_H
+#define _OMAP_CCNT_H
+
+/* ARM ARM B4.1.116 */
+#define OMAP_PMCNTENSET_C (1 << 31) /* Enable PMCCNTR cycle counter */
+
+/* ARM ARM B4.1.117 PMCR */
+#define OMAP_PMCR_DP (1 << 5) /* Disable when ev. cnt. prohibited */
+#define OMAP_PMCR_X (1 << 4) /* Export enable */
+#define OMAP_PMCR_D (1 << 3) /* Clock divider */
+#define OMAP_PMCR_C (1 << 2) /* Cycle counter reset */
+#define OMAP_PMCR_P (1 << 1) /* Event counter reset */
+#define OMAP_PMCR_E (1 << 0) /* Enable event counters */
+
+/* ARM ARM B4.1.119 PMINTENSET */
+#define OMAP_PMINTENSET_C (1 << 31) /* PMCCNTR overflow int req. enable*/
+
+/* ARM ARM B4.1.124 PMUSERENR */
+#define OMAP_PMUSERENR_EN (1 << 0) /* User mode access enable bit */
+
+#endif /* _OMAP_CCNT_H */
#include "omap_intr.h"
static irq_hook_t omap3_timer_hook; /* interrupt handler hook */
+static u64_t tsc;
int omap3_register_timer_handler(const irq_handler_t handler)
{
mmio_clear(OMAP3_GPTIMER1_TCLR, OMAP3_TCLR_ST);
}
-static u64_t tsc;
void omap3_timer_int_handler()
{
/* Clear the interrupt */
tsc++;
}
+/* Don't use libminlib's read_tsc_64, but our own version instead. We emulate
+ * the ARM Cycle Counter (CCNT) with 1 cycle per ms. We can't rely on the
+ * actual counter hardware to be working (i.e., qemu doesn't emulate it at all)
+ */
void read_tsc_64(u64_t *t)
{
*t = tsc;
SRCS+= gcov.c gcov_flush.c
# Various utils
-SRCS+= itoa.c u64util.c
+SRCS+= itoa.c u64util.c read_tsc_64.c
# svrctl
SRCS+= svrctl.c
-SRCS+= get_bp.S
+SRCS+= get_bp.S read_tsc.c
--- /dev/null
+#include <sys/types.h>
+
+void
+read_tsc(u32_t *hi, u32_t *lo)
+{
+/* Read Clock Cycle Counter (CCNT). Intel calls it Time Stamp Counter (TSC) */
+ u32_t ccnt;
+
+ /* Get value from the Performance Monitors Cycle Counter Register.
+ * See ARM Architecture Reference Manual B5.1.113.
+ */
+ asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n" : "=r" (ccnt) : : "%0");
+
+ /* The ARMv7-A clock cycle counter is only 32-bits, but read_tsc is
+ * expected to return a 64-bit value. hi is therefore always 0.
+ */
+ *hi = 0;
+ *lo = ccnt;
+}
+
SRCS+= _cpufeature.c _cpuid.S get_bp.S getprocessor.S \
- read_tsc.S read_tsc_64.c
+ read_tsc.S