source: rtems/c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 3.3 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <leon.h>
16
17#include <rtems/counter.h>
18
19static volatile struct gptimer_regs *adev_to_gpt(struct ambapp_dev *adev)
20{
21  return (volatile struct gptimer_regs *) DEV_TO_APB(adev)->start;
22}
23
24static CPU_Counter_ticks timestamp_counter_difference(
25  CPU_Counter_ticks second,
26  CPU_Counter_ticks first
27)
28{
29  return second - first;
30}
31
32static CPU_Counter_ticks free_counter_difference(
33  CPU_Counter_ticks second,
34  CPU_Counter_ticks first
35)
36{
37  return first - second;
38}
39
40static CPU_Counter_ticks clock_counter_difference(
41  CPU_Counter_ticks second,
42  CPU_Counter_ticks first
43)
44{
45  CPU_Counter_ticks period = rtems_configuration_get_microseconds_per_tick();
46
47  return (first + period - second) % period;
48}
49
50static void gpt_counter_initialize(
51  volatile struct gptimer_regs *gpt,
52  size_t timer_index,
53  uint32_t frequency,
54  SPARC_Counter_difference counter_difference
55)
56{
57  _SPARC_Counter_initialize(
58    (volatile const uint32_t *) &gpt->timer[timer_index].value,
59    counter_difference
60  );
61
62  rtems_counter_initialize_converter(frequency);
63}
64
65static unsigned int get_tstamp(volatile struct irqmp_timestamp_regs *irqmp_ts)
66{
67  return irqmp_ts->control >> 27;
68}
69
70void leon3_cpu_counter_initialize(void)
71{
72  volatile struct irqmp_timestamp_regs *irqmp_ts =
73    &LEON3_IrqCtrl_Regs->timestamp[0];
74  struct ambapp_dev *adev;
75  int idx = 1;
76
77  if (leon3_irqmp_has_timestamp(irqmp_ts)) {
78    /* Use the interrupt controller timestamp counter if available */
79
80    /* Enable interrupt timestamping for an arbitrary interrupt line */
81    irqmp_ts->control = 0x1;
82
83    _SPARC_Counter_initialize(
84      (volatile const uint32_t *) &irqmp_ts->counter,
85      timestamp_counter_difference
86    );
87
88    /* Get and set the frequency */
89    adev = (void *) ambapp_for_each(
90      &ambapp_plb,
91      OPTIONS_ALL | OPTIONS_APB_SLVS,
92      VENDOR_GAISLER,
93      GAISLER_IRQMP,
94      ambapp_find_by_idx,
95      NULL
96    );
97    rtems_counter_initialize_converter(ambapp_freq_get(&ambapp_plb, adev));
98  } else {
99    adev = (void *) ambapp_for_each(
100      &ambapp_plb,
101      OPTIONS_ALL | OPTIONS_APB_SLVS,
102      VENDOR_GAISLER,
103      GAISLER_GPTIMER,
104      ambapp_find_by_idx,
105      &idx
106    );
107    if (adev != NULL) {
108      /* Use the second GPTIMER if available */
109      volatile struct gptimer_regs *gpt = adev_to_gpt(adev);
110      uint32_t max_frequency = ambapp_freq_get(&ambapp_plb, adev);
111      unsigned min_prescaler = 8;
112      uint32_t frequency = max_frequency / min_prescaler;
113
114      gpt->scaler_reload = min_prescaler - 1;
115      gpt->timer[0].reload = 0xffffffff;
116      gpt->timer[0].ctrl = LEON3_GPTIMER_EN | LEON3_GPTIMER_RL
117        | LEON3_GPTIMER_LD;
118
119      gpt_counter_initialize(gpt, 0, frequency, free_counter_difference);
120    } else if (LEON3_Timer_Regs != NULL) {
121      /* Fall back to the first GPTIMER if available */
122      gpt_counter_initialize(
123        LEON3_Timer_Regs,
124        LEON3_CLOCK_INDEX,
125        LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER,
126        clock_counter_difference
127      );
128    }
129  }
130}
Note: See TracBrowser for help on using the repository browser.