1/**
2 * \file
3 * \brief ARM Cortex A9 Global Timer driver.
4 */
5
6/*
7 * Copyright (c) 2015 ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14#include <a9_gt.h>
15#include <maps/a9mpcore_map.h>
16#include <kernel.h>
17#include <paging_kernel_arch.h>
18#include <dev/cortex_a9_gt_dev.h>
19#include <systime.h>
20
21static cortex_a9_gt_t a9_gt;
22static bool initialized = false;
23
24#define MSG(format, ...) \
25    printk( LOG_NOTE, "CortexA9 GT: "format, ## __VA_ARGS__ )
26
27/*
28 * Initialize the timer.  The MMU is on.
29 */
30void a9_gt_init(lpaddr_t addr)
31{
32    assert(!initialized);
33    lvaddr_t gt_base = paging_map_device(addr, A9MPCORE_TIMER_GBL_SIZE);
34    cortex_a9_gt_initialize(&a9_gt, (mackerel_addr_t)gt_base);
35    initialized = true;
36    MSG("initialized at 0x%"PRIxLVADDR"\n", gt_base);
37
38    // set the global timer
39    cortex_a9_gt_TimerControl_timer_enable_wrf(&a9_gt, 0x1);
40    cortex_a9_gt_TimerControl_comp_enable_wrf(&a9_gt, 0x0);
41    cortex_a9_gt_TimerControl_int_enable_wrf(&a9_gt, 0x1);
42    cortex_a9_gt_TimerControl_auto_increment_wrf(&a9_gt, 0x0);
43    cortex_a9_gt_TimerControl_prescale_wrf(&a9_gt, 0x0);
44    a9_gt_ack_irq();
45}
46
47uint64_t a9_gt_read(void)
48{
49    // need to re-read high value according to ARM TRM 4.4.1
50    uint32_t low, high;
51    do {
52        high = cortex_a9_gt_TimerCounterHigh_rd(&a9_gt);
53        low  = cortex_a9_gt_TimerCounterLow_rd(&a9_gt);
54    } while(high != cortex_a9_gt_TimerCounterHigh_rd(&a9_gt));
55
56    return (((uint64_t) high) << 32) | ((uint32_t) low);
57}
58
59uint32_t a9_gt_read_low(void)
60{
61    return cortex_a9_gt_TimerCounterLow_rd(&a9_gt);
62}
63
64uint32_t a9_gt_read_high(void)
65{
66    return cortex_a9_gt_TimerCounterHigh_rd(&a9_gt);
67}
68
69void a9_gt_set_comparator(uint64_t timeout)
70{
71    cortex_a9_gt_TimerControl_comp_enable_wrf(&a9_gt, 0x0);
72    cortex_a9_gt_TimerComparatorLow_wr(&a9_gt, timeout);
73    cortex_a9_gt_TimerComparatorHigh_wr(&a9_gt, timeout >> 32);
74    cortex_a9_gt_TimerControl_comp_enable_wrf(&a9_gt, 0x1);
75}
76
77void a9_gt_ack_irq(void)
78{
79    cortex_a9_gt_TimerIntStat_event_flag_wrf(&a9_gt, 0x1);
80}
81