1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12#ifndef __ARCH_MACHINE_GLOBAL_TIMER_H 13#define __ARCH_MACHINE_GLOBAL_TIMER_H 14 15#include <util.h> 16#include <config.h> 17#include <model/statedata.h> 18 19/* ARM Cortex-A9 MPCore global timer driver 20 * Documentation for this timer is available in 21 * the Cortex-A9 MPCore Technical Reference Manual 22 * section "Global Timer Counter Registers" 23 */ 24struct timer { 25 uint32_t countLower; 26 uint32_t countUpper; 27 uint32_t control; 28 uint32_t isr; 29 uint32_t comparatorLower; 30 uint32_t comparatorUpper; 31 uint32_t autoInc; 32}; 33typedef volatile struct timer timer_t; 34extern timer_t * const globalTimer; 35 36enum control { 37 ENABLE = 0, 38 COMP_ENABLE = 1, 39 IRQ_ENABLE = 2, 40 AUTO_INC = 3, 41 RESERVED = 4, 42 PRESCALER = 8, 43 RESERVED_2 = 16 44}; 45 46/** DONT_TRANSLATE */ 47static inline CONST ticks_t 48getTimerPrecision(void) 49{ 50 return usToTicks(2); 51} 52 53/** DONT_TRANSLATE */ 54static inline ticks_t 55getCurrentTime(void) 56{ 57 uint32_t upper, upper2, lower; 58 59 upper = globalTimer->countUpper; 60 lower = globalTimer->countLower; 61 upper2 = globalTimer->countUpper; 62 63 /* account for race: upper could have increased while we 64 * read lower */ 65 if (upper != upper2) { 66 lower = globalTimer->countLower; 67 } 68 69 return (((ticks_t) upper2 << 32llu) + (ticks_t) lower); 70} 71 72/** DONT_TRANSLATE */ 73static inline void 74setDeadline(ticks_t deadline) 75{ 76 assert(deadline > NODE_STATE(ksCurTime)); 77 /* disable cmp */ 78 globalTimer->control &= ~(BIT(COMP_ENABLE)); 79 /* set low bits */ 80 globalTimer->comparatorLower = (uint32_t) deadline; 81 /* set high bits */ 82 globalTimer->comparatorUpper = (uint32_t) (deadline >> 32llu); 83 /* enable cmp */ 84 globalTimer->control |= BIT(COMP_ENABLE); 85 /* if this fails PRECISION is too low */ 86 assert(getCurrentTime() < deadline || globalTimer->isr == 1u); 87} 88 89/** DONT_TRANSLATE */ 90static inline void 91ackDeadlineIRQ(void) 92{ 93 /* disable cmp */ 94 globalTimer->control &= ~(BIT(COMP_ENABLE)); 95 /* ack the isr */ 96 globalTimer->isr = 1; 97} 98 99#endif /* __ARCH_MACHINE_GLOBAL_TIMER_H */ 100