source: rtems/bsps/shared/dev/clock/arm-generic-timer.c @ 9bf813c5

Last change on this file since 9bf813c5 was 9bf813c5, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 21:38:43

bsps/shared/: Scripted embedded brains header file clean up

Updates #4625.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 * Copyright (c) 2017 embedded brains GmbH.  All rights reserved.
3 *
4 * The license and distribution terms for this file may be
5 * found in the file LICENSE in this distribution or at
6 * http://www.rtems.org/license/LICENSE.
7 */
8
9#include <bsp.h>
10#include <bsp/fatal.h>
11#include <bsp/irq.h>
12#include <bsp/irq-generic.h>
13#include <dev/clock/arm-generic-timer.h>
14
15#include <rtems/counter.h>
16#include <rtems/sysinit.h>
17#include <rtems/timecounter.h>
18#include <rtems/score/smpimpl.h>
19
20/*
21 * Clock driver using the ARMv7-AR/AArch64 Generic Timer.  The BSP must provide the
22 * following function:
23 *
24 * void arm_generic_timer_get_config(uint32_t *frequency, uint32_t *irq);
25 *
26 * The BSP may optionally define ARM_GENERIC_TIMER_USE_VIRTUAL in <bsp.h> to
27 * use the virtual timer instead of the physical timer.
28 */
29
30typedef struct {
31  struct timecounter tc;
32  uint32_t interval;
33  rtems_vector_number irq;
34} arm_gt_clock_context;
35
36static arm_gt_clock_context arm_gt_clock_instance;
37
38/* This is defined in dev/clock/clockimpl.h */
39void Clock_isr(rtems_irq_hdl_param arg);
40
41static void arm_gt_clock_at_tick(void)
42{
43  uint64_t cval;
44  uint32_t interval;
45
46  interval = arm_gt_clock_instance.interval;
47  cval = arm_gt_clock_get_compare_value();
48  cval += interval;
49  arm_gt_clock_set_compare_value(cval);
50#ifdef ARM_GENERIC_TIMER_UNMASK_AT_TICK
51  arm_gt_clock_set_control(0x1);
52#endif /* ARM_GENERIC_TIMER_UNMASK_AT_TICK */
53}
54
55static void arm_gt_clock_handler_install(void)
56{
57  rtems_status_code sc;
58
59  sc = rtems_interrupt_handler_install(
60    arm_gt_clock_instance.irq,
61    "Clock",
62    RTEMS_INTERRUPT_UNIQUE,
63    (rtems_interrupt_handler) Clock_isr,
64    NULL
65  );
66  if (sc != RTEMS_SUCCESSFUL) {
67    bsp_fatal(BSP_ARM_FATAL_GENERIC_TIMER_CLOCK_IRQ_INSTALL);
68  }
69}
70
71static uint32_t arm_gt_clock_get_timecount(struct timecounter *tc)
72{
73  return (uint32_t) arm_gt_clock_get_count();
74}
75
76static void arm_gt_clock_gt_init(uint64_t cval)
77{
78  arm_gt_clock_set_compare_value(cval);
79  arm_gt_clock_set_control(0x1);
80}
81
82#if defined(RTEMS_SMP) && !defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
83static void arm_gt_clock_secondary_action(void *arg)
84{
85  uint64_t *cval;
86
87  cval = arg;
88  arm_gt_clock_gt_init(*cval);
89  bsp_interrupt_vector_enable(arm_gt_clock_instance.irq);
90}
91#endif
92
93static void arm_gt_clock_secondary_initialization(uint64_t cval)
94{
95#if defined(RTEMS_SMP) && !defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
96  _SMP_Broadcast_action(arm_gt_clock_secondary_action, &cval);
97#endif
98}
99
100static void arm_gt_clock_initialize(void)
101{
102  uint64_t frequency;
103  uint64_t us_per_tick;
104  uint32_t interval;
105  uint64_t cval;
106  struct timecounter *tc;
107
108  tc = &arm_gt_clock_instance.tc;
109  frequency = tc->tc_frequency;
110  us_per_tick = rtems_configuration_get_microseconds_per_tick();
111  interval = (uint32_t) ((frequency * us_per_tick) / 1000000);
112  cval = arm_gt_clock_get_count();
113  cval += interval;
114  arm_gt_clock_instance.interval = interval;
115
116  arm_gt_clock_gt_init(cval);
117  arm_gt_clock_secondary_initialization(cval);
118
119  tc->tc_get_timecount = arm_gt_clock_get_timecount;
120  tc->tc_counter_mask = 0xffffffff;
121  tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
122  rtems_timecounter_install(tc);
123}
124
125uint32_t _CPU_Counter_frequency(void)
126{
127  return (uint32_t) arm_gt_clock_instance.tc.tc_frequency;
128}
129
130CPU_Counter_ticks _CPU_Counter_read(void)
131{
132  return (uint32_t) arm_gt_clock_get_count();
133}
134
135static void arm_gt_system_init(void)
136{
137#ifdef ARM_GENERIC_TIMER_SYSTEM_BASE
138  volatile uint32_t *cntcr;
139
140  cntcr = (volatile uint32_t *) ARM_GENERIC_TIMER_SYSTEM_BASE;
141  *cntcr = ARM_GENERIC_TIMER_SYSTEM_CNTCR;
142#endif
143}
144
145static void arm_gt_clock_early_init(void)
146{
147  uint32_t frequency;
148
149  arm_gt_system_init();
150  arm_gt_clock_set_control(0x3);
151  arm_generic_timer_get_config(
152    &frequency,
153    &arm_gt_clock_instance.irq
154  );
155
156  /*
157   * Used by _CPU_Counter_frequency() before arm_gt_clock_initialize() is
158   * called.
159   */
160  arm_gt_clock_instance.tc.tc_frequency = frequency;
161}
162
163RTEMS_SYSINIT_ITEM(
164  arm_gt_clock_early_init,
165  RTEMS_SYSINIT_CPU_COUNTER,
166  RTEMS_SYSINIT_ORDER_FIRST
167);
168
169#define Clock_driver_support_at_tick() \
170  arm_gt_clock_at_tick()
171
172#define Clock_driver_support_initialize_hardware() \
173  arm_gt_clock_initialize()
174
175#define Clock_driver_support_install_isr(isr) \
176  arm_gt_clock_handler_install()
177
178/* Include shared source clock driver code */
179#include "../../shared/dev/clock/clockimpl.h"
Note: See TracBrowser for help on using the repository browser.