File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <rtems.h>
0023 #include <rtems/libio.h>
0024 #include <rtems/clockdrv.h>
0025 #include <stdlib.h> /* for atexit() */
0026 #include <assert.h>
0027 #include <libcpu/c_clock.h>
0028 #include <libcpu/cpuIdent.h>
0029 #include <libcpu/spr.h>
0030 #include <rtems/bspIo.h> /* for printk() */
0031 #include <libcpu/powerpc-utility.h>
0032 #include <rtems/timecounter.h>
0033 #include <rtems/score/percpu.h>
0034 #include <rtems/score/thread.h>
0035
0036 #include <bspopts.h> /* for CLOCK_DRIVER_USE_FAST_IDLE */
0037
0038 SPR_RW(BOOKE_TCR)
0039 SPR_RW(BOOKE_TSR)
0040 SPR_RW(BOOKE_DECAR)
0041
0042 extern int BSP_connect_clock_handler (void);
0043
0044
0045
0046
0047 volatile uint32_t Clock_driver_ticks;
0048
0049
0050
0051
0052 static uint32_t Clock_Decrementer_value;
0053
0054 static struct timecounter Clock_TC;
0055
0056 static uint32_t Clock_Get_timecount(struct timecounter *tc)
0057 {
0058 return ppc_time_base();
0059 }
0060
0061 void clockOff(void* unused)
0062 {
0063 rtems_interrupt_level l;
0064
0065 if ( ppc_cpu_is_bookE() ) {
0066 rtems_interrupt_disable(l);
0067 _write_BOOKE_TCR(_read_BOOKE_TCR() & ~BOOKE_TCR_DIE);
0068 rtems_interrupt_enable(l);
0069 } else {
0070
0071
0072
0073
0074 }
0075 }
0076
0077 void clockOn(void* unused)
0078 {
0079 rtems_interrupt_level l;
0080
0081 PPC_Set_decrementer( Clock_Decrementer_value );
0082
0083 if ( ppc_cpu_is_bookE() ) {
0084 _write_BOOKE_DECAR( Clock_Decrementer_value );
0085
0086 rtems_interrupt_disable(l);
0087
0088
0089 _write_BOOKE_TSR( BOOKE_TSR_DIS );
0090
0091 _write_BOOKE_TCR( _read_BOOKE_TCR() | BOOKE_TCR_DIE );
0092
0093 rtems_interrupt_enable(l);
0094
0095 }
0096 }
0097
0098 static void clockHandler(void)
0099 {
0100 #if (CLOCK_DRIVER_USE_FAST_IDLE == 1)
0101 rtems_interrupt_level level;
0102 uint32_t tb;
0103 Per_CPU_Control *cpu_self;
0104
0105 rtems_interrupt_disable(level);
0106
0107 tb = ppc_time_base();
0108 rtems_timecounter_tick();
0109 cpu_self = _Per_CPU_Get();
0110
0111 while (
0112 cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
0113 && cpu_self->heir == cpu_self->executing
0114 && cpu_self->executing->is_idle
0115 ) {
0116 tb += Clock_Decrementer_value;
0117 ppc_set_time_base( tb );
0118 rtems_timecounter_tick();
0119 }
0120
0121 rtems_interrupt_enable(level);
0122 #else
0123 rtems_timecounter_tick();
0124 #endif
0125 }
0126
0127 static void (*clock_handler)(void);
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 void clockIsr(void *unused)
0143 {
0144 int decr;
0145
0146
0147
0148
0149 do {
0150 register uint32_t flags;
0151
0152 rtems_interrupt_disable(flags);
0153 __asm__ volatile (
0154 "mfdec %0; add %0, %0, %1; mtdec %0"
0155 : "=&r"(decr)
0156 : "r"(Clock_Decrementer_value)
0157 );
0158 rtems_interrupt_enable(flags);
0159
0160 Clock_driver_ticks += 1;
0161
0162
0163
0164 clock_handler();
0165 } while ( decr < 0 );
0166 }
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 void clockIsrBookE(void *unused)
0177 {
0178
0179
0180
0181
0182
0183
0184 Clock_driver_ticks += 1;
0185
0186
0187
0188
0189 clock_handler();
0190 }
0191
0192 int clockIsOn(void* unused)
0193 {
0194 uint32_t msr_value;
0195
0196 _CPU_MSR_GET( msr_value );
0197
0198 if ( ppc_cpu_is_bookE() && ! (_read_BOOKE_TCR() & BOOKE_TCR_DIE) )
0199 msr_value = 0;
0200
0201 if (msr_value & MSR_EE) return 1;
0202
0203 return 0;
0204 }
0205
0206 void _Clock_Initialize( void )
0207 {
0208 rtems_interrupt_level l,tcr;
0209
0210 Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
0211 rtems_configuration_get_milliseconds_per_tick();
0212
0213
0214
0215
0216 PPC_Set_decrementer( (unsigned)-1 );
0217
0218
0219
0220
0221 if ( ppc_cpu_is_bookE() ) {
0222
0223 rtems_interrupt_disable(l);
0224
0225 tcr = _read_BOOKE_TCR();
0226 tcr |= BOOKE_TCR_ARE;
0227 tcr &= ~BOOKE_TCR_DIE;
0228 _write_BOOKE_TCR(tcr);
0229
0230 rtems_interrupt_enable(l);
0231 }
0232
0233 Clock_TC.tc_get_timecount = Clock_Get_timecount;
0234 Clock_TC.tc_counter_mask = 0xffffffff;
0235 Clock_TC.tc_frequency = (UINT64_C(1000) * BSP_bus_frequency) / BSP_time_base_divisor;
0236 Clock_TC.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0237 rtems_timecounter_install(&Clock_TC);
0238
0239
0240
0241
0242
0243
0244
0245
0246 clock_handler = clockHandler;
0247 if (!BSP_connect_clock_handler ()) {
0248 printk("Unable to initialize system clock\n");
0249 rtems_fatal_error_occurred(1);
0250 }
0251 }