source: rtems/bsps/powerpc/shared/clock/clock.c @ e560ee85

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

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

Updates #4625.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSBSPsPowerPCShared
5 *
6 * @brief Source file for a clock driver.
7 */
8
9/*
10 * Copyright (c) 2008-2015 embedded brains GmbH.  All rights reserved.
11 *
12 * The license and distribution terms for this file may be
13 * found in the file LICENSE in this distribution or at
14 * http://www.rtems.org/license/LICENSE.
15 */
16
17#include <rtems.h>
18#include <rtems/clockdrv.h>
19#include <rtems/timecounter.h>
20
21#include <libcpu/powerpc-utility.h>
22#include <bsp/vectors.h>
23
24#define RTEMS_STATUS_CHECKS_USE_PRINTK
25
26#include <rtems/status-checks.h>
27
28/*
29 * This variable must be defined in the BSP and valid before clock driver
30 * initialization.
31 */
32extern uint32_t bsp_time_base_frequency;
33
34#define PPC405_PIT 0x3db
35
36#define PPC_CLOCK_DECREMENTER_MAX UINT32_MAX
37
38volatile uint32_t Clock_driver_ticks = 0;
39
40static uint32_t ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
41
42static uint32_t ppc_clock_next_time_base;
43
44static struct timecounter ppc_tc;
45
46static uint32_t ppc_get_timecount(struct timecounter *tc)
47{
48  return ppc_time_base();
49}
50
51static void ppc_clock_no_tick(void)
52{
53  /* Do nothing */
54}
55
56static void (*ppc_clock_tick)(void) = ppc_clock_no_tick;
57
58static int ppc_clock_exception_handler(
59  BSP_Exception_frame *frame,
60  unsigned number
61)
62{
63  uint32_t delta = ppc_clock_decrementer_value;
64  uint32_t next = ppc_clock_next_time_base;
65  uint32_t dec = 0;
66  uint32_t now = 0;
67  uint32_t msr = 0;
68
69  do {
70    /* Increment clock ticks */
71    Clock_driver_ticks += 1;
72
73    /* Enable external exceptions */
74    msr = ppc_external_exceptions_enable();
75
76    /* Call clock ticker  */
77    ppc_clock_tick();
78
79    /* Restore machine state */
80    ppc_external_exceptions_disable( msr);
81
82    /* Next time base */
83    next += delta;
84
85    /* Current time */
86    now = ppc_time_base();
87
88    /* New decrementer value */
89    dec = next - now;
90  } while (dec > delta);
91
92  /* Set decrementer */
93  ppc_set_decrementer_register( dec);
94
95  /* Expected next time base */
96  ppc_clock_next_time_base = next;
97
98  return 0;
99}
100
101static int ppc_clock_exception_handler_first(
102  BSP_Exception_frame *frame,
103  unsigned number
104)
105{
106  /* We have to clear the first pending decrementer exception this way */
107
108  if (ppc_decrementer_register() >= 0x80000000) {
109    ppc_clock_exception_handler( frame, number);
110  }
111
112  ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler);
113
114  return 0;
115}
116
117static int ppc_clock_exception_handler_booke(
118  BSP_Exception_frame *frame,
119  unsigned number
120)
121{
122  uint32_t msr;
123
124  /* Acknowledge decrementer request */
125  PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS);
126
127  /* Increment clock ticks */
128  Clock_driver_ticks += 1;
129
130  /* Enable external exceptions */
131  msr = ppc_external_exceptions_enable();
132
133  /* Call clock ticker  */
134  ppc_clock_tick();
135
136  /* Restore machine state */
137  ppc_external_exceptions_disable( msr);
138
139  return 0;
140}
141
142static int ppc_clock_exception_handler_ppc405(BSP_Exception_frame *frame, unsigned number)
143{
144  uint32_t msr;
145
146  /* Acknowledge PIT request */
147  PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_TSR, BOOKE_TSR_DIS);
148
149  /* Increment clock ticks */
150  Clock_driver_ticks += 1;
151
152  /* Enable external exceptions */
153  msr = ppc_external_exceptions_enable();
154
155  /* Call clock ticker  */
156  ppc_clock_tick();
157
158  /* Restore machine state */
159  ppc_external_exceptions_disable(msr);
160
161  return 0;
162}
163
164void _Clock_Initialize( void )
165{
166  uint64_t frequency = bsp_time_base_frequency;
167  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
168  uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);
169
170  /*
171   * Set default ticker.
172   */
173  ppc_clock_tick = rtems_timecounter_tick;
174
175  if (ppc_cpu_is_bookE() != PPC_BOOKE_405) {
176    /* Decrementer value */
177    ppc_clock_decrementer_value = interval - 1;
178
179    /* Check decrementer value */
180    if (ppc_clock_decrementer_value == 0) {
181      ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
182      RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
183    }
184    if (ppc_cpu_is_bookE()) {
185      /* Set decrementer auto-reload value */
186      PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);
187
188      /* Install exception handler */
189      ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke);
190
191      /* Enable decrementer and auto-reload */
192      PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
193    } else {
194      /* Here the decrementer value is actually the interval */
195      ++ppc_clock_decrementer_value;
196
197      /* Initialize next time base */
198      ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;
199
200      /* Install exception handler */
201      ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
202    }
203
204    /* Set the decrementer value */
205    ppc_set_decrementer_register( ppc_clock_decrementer_value);
206  } else {
207    /* PIT interval value */
208    ppc_clock_decrementer_value = interval;
209
210    /* Install exception handler */
211    ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405);
212
213    /* Enable PIT and auto-reload */
214    PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
215
216    /* Set PIT auto-reload and initial value */
217    PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval);
218  }
219
220  /* Install timecounter */
221  ppc_tc.tc_get_timecount = ppc_get_timecount;
222  ppc_tc.tc_counter_mask = 0xffffffff;
223  ppc_tc.tc_frequency = frequency;
224  ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
225  rtems_timecounter_install(&ppc_tc);
226}
Note: See TracBrowser for help on using the repository browser.