1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <util.h> 10#include <config.h> 11#include <model/statedata.h> 12 13#ifndef CONFIG_KERNEL_MCS 14#error "This driver should only be selected for MCS kernel" 15#endif /* CONFIG_KERNEL_MCS */ 16 17/* ARM Cortex-A9 MPCore global timer driver 18 * Documentation for this timer is available in 19 * the Cortex-A9 MPCore Technical Reference Manual 20 * section "Global Timer Counter Registers" 21 */ 22struct timer { 23 uint32_t countLower; 24 uint32_t countUpper; 25 uint32_t control; 26 uint32_t isr; 27 uint32_t comparatorLower; 28 uint32_t comparatorUpper; 29 uint32_t autoInc; 30}; 31typedef volatile struct timer timer_t; 32extern timer_t *const globalTimer; 33 34enum control { 35 ENABLE = 0, 36 COMP_ENABLE = 1, 37 IRQ_ENABLE = 2, 38 AUTO_INC = 3, 39 RESERVED = 4, 40 PRESCALER = 8, 41 RESERVED_2 = 16 42}; 43 44/** DONT_TRANSLATE */ 45static inline ticks_t getCurrentTime(void) 46{ 47 uint32_t upper, upper2, lower; 48 49 upper = globalTimer->countUpper; 50 lower = globalTimer->countLower; 51 upper2 = globalTimer->countUpper; 52 53 /* account for race: upper could have increased while we 54 * read lower */ 55 if (upper != upper2) { 56 lower = globalTimer->countLower; 57 } 58 59 return (((ticks_t) upper2 << 32llu) + (ticks_t) lower); 60} 61 62/** DONT_TRANSLATE */ 63static inline void setDeadline(ticks_t deadline) 64{ 65 /* disable cmp */ 66 globalTimer->control &= ~(BIT(COMP_ENABLE)); 67 /* set low bits */ 68 globalTimer->comparatorLower = (uint32_t) deadline; 69 /* set high bits */ 70 globalTimer->comparatorUpper = (uint32_t)(deadline >> 32llu); 71 /* enable cmp */ 72 globalTimer->control |= BIT(COMP_ENABLE); 73 /* if this fails PRECISION is too low */ 74 assert(getCurrentTime() < deadline || globalTimer->isr == 1u); 75} 76 77/** DONT_TRANSLATE */ 78static inline void ackDeadlineIRQ(void) 79{ 80 /* disable cmp */ 81 globalTimer->control &= ~(BIT(COMP_ENABLE)); 82 /* ack the isr */ 83 globalTimer->isr = 1; 84} 85 86 87