File indexing completed on 2025-05-11 08:24:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include <rtems.h>
0040 #include <rtems/timecounter.h>
0041 #include <rtems/clockdrv.h>
0042 #include <stdlib.h>
0043 #include <bsp.h>
0044 #include <grlib/tlib.h>
0045
0046 #ifdef RTEMS_DRVMGR_STARTUP
0047
0048 #if defined(LEON3)
0049 #include <leon.h>
0050 #endif
0051
0052 struct ops {
0053
0054
0055
0056
0057 rtems_device_driver (*initialize_counter)(void);
0058
0059
0060
0061
0062
0063
0064
0065 rtems_device_driver (*at_tick)(void);
0066
0067
0068
0069
0070
0071 void (*timecounter_tick)(void);
0072
0073
0074
0075
0076
0077
0078 void (*shutdown_hardware)(void);
0079 };
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 #ifndef RTEMS_SMP
0090
0091 static const struct ops ops_simple;
0092 #else
0093
0094 static const struct ops ops_timetag;
0095
0096 static const struct ops ops_irqamp;
0097
0098 static const struct ops ops_subtimer;
0099 #endif
0100
0101 struct clock_priv {
0102 const struct ops *ops;
0103
0104
0105
0106
0107 int tlib_tick_index;
0108
0109 int tlib_counter_index;
0110 void *tlib_tick;
0111 void *tlib_counter;
0112 rtems_timecounter_simple tc_simple;
0113 struct timecounter tc;
0114 };
0115 static struct clock_priv priv;
0116
0117
0118
0119
0120 void Clock_timer_register(int timer_number)
0121 {
0122 priv.tlib_tick_index = timer_number;
0123 priv.tlib_counter_index = timer_number + 1;
0124 }
0125
0126 static rtems_device_driver tlib_clock_find_timer(void)
0127 {
0128
0129 priv.tlib_tick = tlib_open(priv.tlib_tick_index);
0130 if (priv.tlib_tick == NULL) {
0131
0132 return RTEMS_NOT_DEFINED;
0133 }
0134
0135
0136 #ifndef RTEMS_SMP
0137 priv.ops = &ops_simple;
0138 #else
0139
0140 leon3_up_counter_enable();
0141 if (leon3_up_counter_is_available()) {
0142 priv.ops = &ops_timetag;
0143 return RTEMS_SUCCESSFUL;
0144 } else {
0145 volatile struct irqmp_timestamp_regs *irqmp_ts;
0146
0147 irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
0148 if (irqmp_has_timestamp(irqmp_ts)) {
0149 priv.ops = &ops_irqamp;
0150 return RTEMS_SUCCESSFUL;
0151 }
0152 }
0153
0154
0155 priv.ops = &ops_subtimer;
0156 #endif
0157
0158 return RTEMS_SUCCESSFUL;
0159 }
0160
0161 static rtems_device_driver tlib_clock_initialize_hardware(void)
0162 {
0163
0164 tlib_set_freq(priv.tlib_tick, rtems_configuration_get_microseconds_per_tick());
0165 priv.ops->initialize_counter();
0166 tlib_start(priv.tlib_tick, 0);
0167
0168 return RTEMS_SUCCESSFUL;
0169 }
0170
0171 static rtems_device_driver tlib_clock_at_tick(void)
0172 {
0173 if (priv.ops->at_tick) {
0174 return priv.ops->at_tick();
0175 }
0176
0177 return RTEMS_SUCCESSFUL;
0178 }
0179
0180 static void tlib_clock_timecounter_tick(void)
0181 {
0182 priv.ops->timecounter_tick();
0183 }
0184
0185 static void tlib_clock_install_isr(rtems_isr *isr)
0186 {
0187 int flags = 0;
0188
0189 #ifdef RTEMS_SMP
0190
0191 flags = TLIB_FLAGS_BROADCAST;
0192 #endif
0193 tlib_irq_register(priv.tlib_tick, isr, NULL, flags);
0194 }
0195
0196 #ifndef RTEMS_SMP
0197
0198 static uint32_t simple_tlib_tc_get(rtems_timecounter_simple *tc)
0199 {
0200 unsigned int clicks = 0;
0201
0202 if (priv.tlib_tick != NULL) {
0203 tlib_get_counter(priv.tlib_tick, &clicks);
0204 }
0205
0206 return clicks;
0207 }
0208
0209 static bool simple_tlib_tc_is_pending(rtems_timecounter_simple *tc)
0210 {
0211 bool pending = false;
0212
0213 if (priv.tlib_tick != NULL) {
0214 pending = tlib_interrupt_pending(priv.tlib_tick, 0) != 0;
0215 }
0216
0217 return pending;
0218 }
0219
0220 static uint32_t simple_tlib_tc_get_timecount(struct timecounter *tc)
0221 {
0222 return rtems_timecounter_simple_downcounter_get(
0223 tc,
0224 simple_tlib_tc_get,
0225 simple_tlib_tc_is_pending
0226 );
0227 }
0228
0229 static rtems_device_driver simple_initialize_counter(void)
0230 {
0231 unsigned int tick_hz, frequency;
0232
0233 tlib_get_freq(priv.tlib_tick, &frequency, NULL);
0234 tick_hz = rtems_configuration_get_microseconds_per_tick();
0235
0236 rtems_timecounter_simple_install(
0237 &priv.tc_simple,
0238 (uint64_t)frequency,
0239 tick_hz,
0240 simple_tlib_tc_get_timecount
0241 );
0242
0243 return RTEMS_NOT_DEFINED;
0244 }
0245
0246 static void simple_tlib_tc_at_tick(rtems_timecounter_simple *tc)
0247 {
0248
0249 }
0250
0251
0252
0253
0254
0255 static rtems_device_driver simple_at_tick(void)
0256 {
0257 if (tlib_interrupt_pending(priv.tlib_tick, 1) == 0) {
0258 return RTEMS_NOT_DEFINED;
0259 }
0260 return RTEMS_SUCCESSFUL;
0261 }
0262
0263 static void simple_timecounter_tick(void)
0264 {
0265 rtems_timecounter_simple_downcounter_tick(
0266 &priv.tc_simple,
0267 simple_tlib_tc_get,
0268 simple_tlib_tc_at_tick
0269 );
0270 }
0271
0272 static const struct ops ops_simple = {
0273 .initialize_counter = simple_initialize_counter,
0274 .at_tick = simple_at_tick,
0275 .timecounter_tick = simple_timecounter_tick,
0276 .shutdown_hardware = NULL,
0277 };
0278
0279 #else
0280
0281
0282 static uint32_t subtimer_get_timecount(struct timecounter *tc)
0283 {
0284 unsigned int counter;
0285
0286 tlib_get_counter(priv.tlib_counter, &counter);
0287
0288 return 0xffffffff - counter;
0289 }
0290
0291 static rtems_device_driver subtimer_initialize_counter(void)
0292 {
0293 unsigned int mask;
0294 unsigned int basefreq;
0295
0296 if (priv.tlib_counter_index == priv.tlib_tick_index) {
0297 priv.tlib_counter_index = priv.tlib_tick_index + 1;
0298 }
0299
0300 priv.tlib_counter = tlib_open(priv.tlib_counter_index);
0301 if (priv.tlib_counter == NULL) {
0302
0303 return RTEMS_NOT_DEFINED;
0304 }
0305
0306
0307 tlib_get_freq(priv.tlib_counter, &basefreq, NULL);
0308 tlib_get_widthmask(priv.tlib_counter, &mask);
0309
0310 priv.tc.tc_get_timecount = subtimer_get_timecount;
0311 priv.tc.tc_counter_mask = mask;
0312 priv.tc.tc_frequency = basefreq;
0313 priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0314 rtems_timecounter_install(&priv.tc);
0315
0316 tlib_start(priv.tlib_counter, 0);
0317
0318 return RTEMS_SUCCESSFUL;
0319 }
0320
0321 static void subtimer_timecounter_tick(void)
0322 {
0323 rtems_timecounter_tick();
0324 }
0325
0326 static void subtimer_shutdown_hardware(void)
0327 {
0328 if (priv.tlib_counter) {
0329 tlib_stop(priv.tlib_counter);
0330 priv.tlib_counter = NULL;
0331 }
0332 }
0333
0334 static const struct ops ops_subtimer = {
0335 .initialize_counter = subtimer_initialize_counter,
0336 .timecounter_tick = subtimer_timecounter_tick,
0337 .shutdown_hardware = subtimer_shutdown_hardware,
0338 };
0339
0340
0341 static uint32_t timetag_get_timecount(struct timecounter *tc)
0342 {
0343 return leon3_up_counter_low();
0344 }
0345
0346 static rtems_device_driver timetag_initialize_counter(void)
0347 {
0348
0349 priv.tc.tc_get_timecount = timetag_get_timecount;
0350 priv.tc.tc_counter_mask = 0xffffffff;
0351 priv.tc.tc_frequency = leon3_up_counter_frequency();
0352 priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0353 rtems_timecounter_install(&priv.tc);
0354
0355 return RTEMS_SUCCESSFUL;
0356 }
0357
0358 static void timetag_timecounter_tick(void)
0359 {
0360 rtems_timecounter_tick();
0361 }
0362
0363 static const struct ops ops_timetag = {
0364 .initialize_counter = timetag_initialize_counter,
0365 .at_tick = NULL,
0366 .timecounter_tick = timetag_timecounter_tick,
0367 .shutdown_hardware = NULL,
0368 };
0369
0370
0371 static uint32_t irqamp_get_timecount(struct timecounter *tc)
0372 {
0373 return LEON3_IrqCtrl_Regs->timestamp[0].counter;
0374 }
0375
0376 static rtems_device_driver irqamp_initialize_counter(void)
0377 {
0378 volatile struct irqmp_timestamp_regs *irqmp_ts;
0379 static const uint32_t A_TSISEL_FIELD = 0xf;
0380
0381
0382 priv.tc.tc_get_timecount = irqamp_get_timecount;
0383 priv.tc.tc_counter_mask = 0xffffffff;
0384 priv.tc.tc_frequency = leon3_up_counter_frequency();
0385 priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0386 rtems_timecounter_install(&priv.tc);
0387
0388
0389
0390
0391
0392 irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
0393 irqmp_ts->control = A_TSISEL_FIELD;
0394
0395 return RTEMS_SUCCESSFUL;
0396 }
0397
0398 static void irqamp_timecounter_tick(void)
0399 {
0400 rtems_timecounter_tick();
0401 }
0402
0403 static const struct ops ops_irqamp = {
0404 .initialize_counter = irqamp_initialize_counter,
0405 .at_tick = NULL,
0406 .timecounter_tick = irqamp_timecounter_tick,
0407 .shutdown_hardware = NULL,
0408 };
0409 #endif
0410
0411
0412 #define Clock_driver_support_find_timer() \
0413 do { \
0414 rtems_device_driver ret; \
0415 ret = tlib_clock_find_timer(); \
0416 if (RTEMS_SUCCESSFUL != ret) { \
0417 return ret; \
0418 } \
0419 } while (0)
0420
0421 #define Clock_driver_support_install_isr( isr ) \
0422 tlib_clock_install_isr( isr )
0423
0424 #define Clock_driver_support_set_interrupt_affinity(online_processors) \
0425
0426
0427 #define Clock_driver_support_initialize_hardware() \
0428 do { \
0429 rtems_device_driver ret; \
0430 ret = tlib_clock_initialize_hardware(); \
0431 if (RTEMS_SUCCESSFUL != ret) { \
0432 return ret; \
0433 } \
0434 } while (0)
0435
0436 #define Clock_driver_timecounter_tick(arg) \
0437 tlib_clock_timecounter_tick()
0438
0439 #define Clock_driver_support_at_tick(arg) \
0440 do { \
0441 rtems_device_driver ret; \
0442 ret = tlib_clock_at_tick(); \
0443 if (RTEMS_SUCCESSFUL != ret) { \
0444 return; \
0445 } \
0446 } while (0)
0447
0448 #include "../../../shared/dev/clock/clockimpl.h"
0449
0450 #endif
0451