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 BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <stdio.h> 14#include <assert.h> 15#include <errno.h> 16#include <stdlib.h> 17#include <utils/util.h> 18#include "../../arch/arm/clock.h" 19#include <platsupport/timer.h> 20#include <platsupport/plat/spt.h> 21 22/* The arm timer on the BCM2837 is based on a SP804 timer with some modifications 23 24 - Only one timer 25 - It only runs in continuous mode 26 - Can be set to either stop or continue in ARM debug halt mode 27 - Pre-scale options are only 1, 16 and 256 28 - CLK source is 250 MHz before prescale. 29 - Has an additional up counter register that will count up on each timer tick and 30 roll over without generating interrupts. It has its own prescalar. 31 32 Functions by setting a value in the load register which the timer will move to the value 33 register and when the value counts down to zero, an interrupt will occur if interrupts are 34 enabled and the value from the load register will be copied back into the value register. 35 36 */ 37 38enum { 39 /* 40 Width of the counter. 41 0: 16-bit counters 42 1: 32-bit counters 43 */ 44 COUNTER_WIDTH_BIT = 1, 45 /* 46 The prescale bits select the prescale for the down counter. 47 Note: There are other pre-scale bits in this register (16:23) for 48 the separate free running up-counting counter. 49 00 : pre-scale is clock / 1 (No pre-scale) 50 01 : pre-scale is clock / 16 51 10 : pre-scale is clock / 256 52 11 : pre-scale is clock / 1 53 */ 54 PRESCALE_BIT = 2, 55 56 /* 57 Interrupt enable bit. 58 0: Timer interrupt disabled 59 1: Timer interrupt enabled 60 */ 61 TIMER_INTERRUPT_ENABLE = 5, 62 63 /* 64 Timer enable. 65 0: Disabled 66 1: Enabled 67 */ 68 TIMER_ENABLE = 7, 69 70 /* 71 Timer behaviour when ARM is in debug halt mode: 72 0: Timers keep running 73 1: Timers halted. 74 */ 75 ARM_DEBUG_HALT = 8, 76 77 /* 78 Whether the free-run counter is enabled. 79 0: Enabled 80 1: Disabled 81 */ 82 FREE_RUN_ENABLE = 9, 83 84 /* 85 Free running scalar. 8 bits wide. Reset value is 0x3E 86 Freq = clk/(prescale + 1) 87 */ 88 FREE_RUN_PRESCALE = 16 89} control_reg; 90 91#define LOAD_WIDTH 32 92#define VALUE_WIDTH 32 93#define CTRL_WIDTH 24 94#define IRQ_CLEAR_WIDTH 32 95#define RAW_IRQ_WIDTH 1 96#define MASKED_IRQ_WIDTH 1 97#define PRE_DIVIDER_WIDTH 10 98 99#define TIMER_BASE_OFFSET 0x400 100 101int spt_start(spt_t *spt) 102{ 103 if (spt == NULL) { 104 return EINVAL; 105 } 106 /* Enable timer */ 107 spt->regs->ctrl = BIT(FREE_RUN_ENABLE) | BIT(COUNTER_WIDTH_BIT); 108 return 0; 109} 110 111int spt_stop(spt_t *spt) 112{ 113 if (!spt) { 114 return EINVAL; 115 } 116 /* Disable timer */ 117 spt->regs->ctrl = 0; 118 return 0; 119} 120 121/* Set up the timer to fire an interrupt every ns nanoseconds. 122 * The first such interrupt may arrive before ns nanoseconds 123 * have passed since calling. */ 124int spt_set_timeout(spt_t *spt, uint64_t ns) 125{ 126 if (!spt) { 127 return EINVAL; 128 } 129 uint64_t ticks = ns / (NS_IN_US / (spt->freq / MHZ)); 130 uint32_t prescale_bits = 0; 131 spt->counter_start = ns; 132 if (ticks == 0) { 133 ZF_LOGE("ns too low: %llu\n", ns); 134 return EINVAL; 135 } 136 137 /* Prescale only has 3 values, so we need to calculate them here */ 138 if (ticks >= (UINT32_MAX + 1)) { 139 ticks /= 16; 140 if (ticks >= (1ULL << 32)) { 141 ticks /= 16; 142 if (ticks >= (1ULL << 32)) { 143 ZF_LOGE("ns too high: %llu\n", ns); 144 return EINVAL; 145 } else { 146 prescale_bits = 2; 147 } 148 } else { 149 prescale_bits = 1; 150 } 151 } 152 153 /* Configure timer */ 154 spt->regs->load = ticks; 155 spt->regs->pre_divider = 0; 156 spt->regs->irq_clear = 1; 157 spt->regs->ctrl = BIT(COUNTER_WIDTH_BIT) | (prescale_bits << PRESCALE_BIT) | 158 BIT(TIMER_INTERRUPT_ENABLE) | BIT(FREE_RUN_ENABLE) | BIT(TIMER_ENABLE); 159 160 return 0; 161} 162 163int spt_handle_irq(spt_t *spt) 164{ 165 if (!spt) { 166 return EINVAL; 167 } 168 if (spt->regs->masked_irq) { 169 spt->regs->irq_clear = 1; 170 spt->regs->ctrl &= ~(BIT(TIMER_ENABLE)); 171 } else { 172 ZF_LOGW("handle irq called when no interrupt pending\n"); 173 return EINVAL; 174 } 175 return 0; 176} 177 178uint64_t spt_get_time(spt_t *spt) 179{ 180 uint64_t value = spt->regs->free_run_count; 181 /* convert raw count to ns. As we never change the free run prescaler we do not need to 182 * scale by it. We multiplly by mhz as the free run count is a 32-bit value so we will 183 * not overflow a 64-bit value at that point */ 184 uint64_t ns = (value * MHZ / spt->freq) * NS_IN_US; 185 return ns; 186} 187 188int spt_init(spt_t *spt, spt_config_t config) 189{ 190 clk_t *clk; 191 192 if (!spt || !config.vaddr) { 193 return EINVAL; 194 } 195 196 /* Save the mmio address */ 197 spt->regs = (void *) ((uintptr_t) config.vaddr) + TIMER_BASE_OFFSET; 198 clock_sys_t clk_sys; 199 clock_sys_init_default(&clk_sys); 200 clk = clk_get_clock(&clk_sys, CLK_SP804); 201 spt->freq = clk_get_freq(clk); 202 203 /* handle any pending irqs */ 204 spt_handle_irq(spt); 205 return 0; 206} 207