File indexing completed on 2025-05-11 08:24:08
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 #include <bsp/leon3.h>
0037 #include <grlib/irqamp.h>
0038
0039 #include <rtems/counter.h>
0040 #include <rtems/sysinit.h>
0041 #include <rtems/timecounter.h>
0042
0043 #if defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
0044 defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
0045 static uint32_t leon3_timecounter_get_asr_22_23_up_counter(
0046 struct timecounter *tc
0047 )
0048 {
0049 return leon3_up_counter_low();
0050 }
0051
0052 static void leon3_counter_use_asr_22_23_up_counter(leon3_timecounter *tc)
0053 {
0054 #if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
0055 tc->base.tc_get_timecount = leon3_timecounter_get_asr_22_23_up_counter;
0056 #endif
0057 tc->base.tc_frequency = leon3_up_counter_frequency();
0058 }
0059 #endif
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 #if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
0070
0071 CPU_Counter_ticks _CPU_Counter_read(void)
0072 {
0073 return leon3_up_counter_low();
0074 }
0075
0076 RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
0077
0078 #define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_asr_22_23_up_counter
0079
0080 #elif defined(LEON3_DSU_BASE)
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 #define LEON3_DSU_TIME_TAG_ZERO_BITS 2
0091
0092 static uint32_t leon3_read_dsu_time_tag(void)
0093 {
0094 uint32_t value;
0095 volatile uint32_t *reg;
0096
0097
0098 reg = (uint32_t *) (LEON3_DSU_BASE + 8);
0099 __asm__ volatile (
0100 "\tlda\t[%1]1, %0"
0101 : "=&r"(value)
0102 : "r"(reg)
0103 );
0104 return value << LEON3_DSU_TIME_TAG_ZERO_BITS;
0105 }
0106
0107 static uint32_t leon3_timecounter_get_dsu_time_tag(
0108 struct timecounter *tc
0109 )
0110 {
0111 (void) tc;
0112 return leon3_read_dsu_time_tag();
0113 }
0114
0115 CPU_Counter_ticks _CPU_Counter_read(void)
0116 {
0117 return leon3_read_dsu_time_tag();
0118 }
0119
0120 RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
0121
0122 static void leon3_counter_use_dsu_time_tag(leon3_timecounter *tc)
0123 {
0124 tc->base.tc_frequency =
0125 leon3_processor_local_bus_frequency() << LEON3_DSU_TIME_TAG_ZERO_BITS;
0126 }
0127
0128 #define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_dsu_time_tag
0129
0130 #else
0131
0132
0133
0134
0135
0136 __asm__ (
0137 "\t.section\t\".text\"\n"
0138 "\t.align\t4\n"
0139 "\t.globl\t_CPU_Counter_read\n"
0140 "\t.globl\t_SPARC_Counter_read_ISR_disabled\n"
0141 "\t.type\t_CPU_Counter_read, #function\n"
0142 "\t.type\t_SPARC_Counter_read_ISR_disabled, #function\n"
0143 "_CPU_Counter_read:\n"
0144 "_SPARC_Counter_read_ISR_disabled:\n"
0145 "\tsethi\t%hi(leon3_timecounter_instance), %o0\n"
0146 "\tld [%o0 + %lo(leon3_timecounter_instance)], %o1\n"
0147 "\tor\t%o0, %lo(leon3_timecounter_instance), %o0\n"
0148 "\tor\t%o7, %g0, %g1\n"
0149 "\tcall\t%o1, 0\n"
0150 "\t or\t%g1, %g0, %o7\n"
0151 "\t.previous\n"
0152 );
0153
0154 static uint32_t leon3_timecounter_get_dummy(struct timecounter *base)
0155 {
0156 leon3_timecounter *tc;
0157 uint32_t counter;
0158
0159 tc = (leon3_timecounter *) base;
0160 counter = tc->software_counter + 1;
0161 tc->software_counter = counter;
0162 return counter;
0163 }
0164
0165 #define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_dummy
0166
0167 static uint32_t leon3_timecounter_get_counter_down(struct timecounter *base)
0168 {
0169 leon3_timecounter *tc;
0170
0171 tc = (leon3_timecounter *) base;
0172 return -(*tc->counter_register);
0173 }
0174
0175 static void leon3_counter_use_gptimer(
0176 leon3_timecounter *tc,
0177 gptimer *gpt
0178 )
0179 {
0180 gptimer_timer *timer;
0181
0182 timer = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX];
0183
0184
0185 grlib_store_32(&timer->trldval, 0xffffffff);
0186 grlib_store_32(&timer->tctrl, GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS);
0187
0188 tc->counter_register = &timer->tcntval;
0189 tc->base.tc_get_timecount = leon3_timecounter_get_counter_down;
0190 #if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
0191 tc->base.tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
0192 #else
0193 tc->base.tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
0194 (grlib_load_32(&gpt->sreload) + 1);
0195 #endif
0196 }
0197
0198 #if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
0199
0200 static uint32_t leon3_timecounter_get_counter_up(struct timecounter *base)
0201 {
0202 leon3_timecounter *tc;
0203
0204 tc = (leon3_timecounter *) base;
0205 return *tc->counter_register;
0206 }
0207
0208 static void leon3_counter_use_irqamp_timestamp(
0209 leon3_timecounter *tc,
0210 irqamp_timestamp *irqmp_ts
0211 )
0212 {
0213
0214 grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
0215
0216 tc->counter_register = &irqmp_ts->itcnt;
0217 tc->base.tc_get_timecount = leon3_timecounter_get_counter_up;
0218 tc->base.tc_frequency = leon3_processor_local_bus_frequency();
0219 }
0220
0221 #endif
0222 #endif
0223
0224 leon3_timecounter leon3_timecounter_instance = {
0225 .base = {
0226 .tc_get_timecount = LEON3_GET_TIMECOUNT_INIT,
0227 .tc_counter_mask = 0xffffffff,
0228 .tc_frequency = 1000000000,
0229 .tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER
0230 }
0231 };
0232
0233 uint32_t _CPU_Counter_frequency(void)
0234 {
0235 return leon3_timecounter_instance.base.tc_frequency;
0236 }
0237
0238 static void leon3_counter_initialize(void)
0239 {
0240 #if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
0241
0242 leon3_up_counter_enable();
0243 leon3_counter_use_asr_22_23_up_counter(&leon3_timecounter_instance);
0244
0245 #elif defined(LEON3_DSU_BASE)
0246
0247 leon3_counter_use_dsu_time_tag(&leon3_timecounter_instance);
0248
0249 #else
0250
0251
0252
0253 #if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
0254 irqamp_timestamp *irqmp_ts;
0255 #endif
0256 gptimer *gpt;
0257 leon3_timecounter *tc;
0258
0259 tc = &leon3_timecounter_instance;
0260
0261 #if defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
0262 leon3_up_counter_enable();
0263
0264 if (leon3_up_counter_is_available()) {
0265
0266 leon3_counter_use_asr_22_23_up_counter(tc);
0267 return;
0268 }
0269 #endif
0270
0271 #if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
0272 irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
0273
0274 if (irqmp_ts != NULL) {
0275
0276 leon3_counter_use_irqamp_timestamp(tc, irqmp_ts);
0277 return;
0278 }
0279 #endif
0280
0281 gpt = LEON3_Timer_Regs;
0282
0283 #if defined(LEON3_GPTIMER_BASE)
0284 leon3_counter_use_gptimer(tc, gpt);
0285 #else
0286 if (gpt != NULL) {
0287
0288 leon3_counter_use_gptimer(tc, gpt);
0289 }
0290 #endif
0291
0292 #endif
0293 }
0294
0295 RTEMS_SYSINIT_ITEM(
0296 leon3_counter_initialize,
0297 RTEMS_SYSINIT_CPU_COUNTER,
0298 RTEMS_SYSINIT_ORDER_FIRST
0299 );