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
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include <rtems.h>
0040 #include <rtems/clockdrv.h>
0041 #include <rtems/libio.h>
0042 #include <stdlib.h> /* for atexit() */
0043 #include <rtems/bspIo.h>
0044 #include <rtems/powerpc/powerpc.h>
0045
0046
0047
0048
0049
0050 #include <bsp.h>
0051
0052 #include <bsp/vectors.h>
0053 #include <bsp/irq.h>
0054
0055 extern uint32_t bsp_clicks_per_usec;
0056
0057 volatile uint32_t Clock_driver_ticks;
0058 static uint32_t pit_value, tick_time;
0059 static bool auto_restart;
0060
0061 static void Clock_exit( void );
0062
0063 static inline uint32_t get_itimer(void)
0064 {
0065 register uint32_t rc;
0066
0067 #ifndef ppc405
0068 __asm__ volatile ("mfspr %0, 0x3dd" : "=r" ((rc)));
0069 #else
0070 __asm__ volatile ("mfspr %0, 0x10c" : "=r" ((rc)));
0071 #endif
0072
0073 return rc;
0074 }
0075
0076
0077
0078
0079 static void Clock_isr(void* handle)
0080 {
0081 uint32_t clicks_til_next_interrupt;
0082 #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL)
0083 uint32_t l_orig = _ISR_Get_level();
0084 #endif
0085
0086 if (!auto_restart) {
0087 uint32_t itimer_value;
0088
0089
0090
0091
0092 itimer_value = get_itimer();
0093 tick_time += pit_value;
0094
0095
0096
0097
0098
0099
0100
0101 clicks_til_next_interrupt = tick_time - itimer_value;
0102
0103
0104
0105
0106
0107
0108 if (clicks_til_next_interrupt < 400) {
0109 tick_time = itimer_value + 1000;
0110 clicks_til_next_interrupt = 1000;
0111
0112 }
0113
0114
0115
0116
0117
0118 if (clicks_til_next_interrupt > pit_value) {
0119 tick_time = itimer_value + 1000;
0120 clicks_til_next_interrupt = 1000;
0121
0122 }
0123
0124 __asm__ volatile ("mtspr 0x3db, %0" :: "r"
0125 (clicks_til_next_interrupt));
0126 }
0127
0128 __asm__ volatile ("mtspr 0x3d8, %0" :: "r" (0x08000000));
0129
0130 Clock_driver_ticks++;
0131
0132
0133 #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL)
0134 _ISR_Set_level(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL);
0135 #endif
0136 rtems_clock_tick();
0137
0138 #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL)
0139 _ISR_Set_level(l_orig)
0140 #endif
0141 }
0142
0143 static int ClockIsOn(const rtems_irq_connect_data* unused)
0144 {
0145 register uint32_t tcr;
0146
0147 __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr)));
0148
0149 return (tcr & 0x04000000) != 0;
0150 }
0151
0152 static void ClockOff(const rtems_irq_connect_data* unused)
0153 {
0154 register uint32_t tcr;
0155
0156 __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr)));
0157 tcr &= ~ 0x04400000;
0158 __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr)));
0159 }
0160
0161 static void ClockOn(const rtems_irq_connect_data* unused)
0162 {
0163 uint32_t iocr;
0164 register uint32_t tcr;
0165 #ifndef ppc405
0166 uint32_t pvr;
0167 #endif
0168
0169 Clock_driver_ticks = 0;
0170
0171 #ifndef ppc405
0172 __asm__ volatile ("mfdcr %0, 0xa0" : "=r" (iocr));
0173 iocr &= ~4;
0174 __asm__ volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr));
0175
0176 __asm__ volatile ("mfspr %0, 0x11f" : "=r" ((pvr)));
0177 if (((pvr & 0xffff0000) >> 16) != 0x0020)
0178 return;
0179
0180 if ((pvr & 0xff00) == 0x0000)
0181 #if 0
0182 auto_restart = (pvr & 0x00f0) > 0x0000 ? true : false;
0183 #else
0184
0185 auto_restart = false;
0186 #endif
0187 else if ((pvr & 0xff00) == 0x0100)
0188 auto_restart = true;
0189
0190 #else
0191 __asm__ volatile (
0192 ".machine \"push\"\n"
0193 ".machine \"any\"\n"
0194 "mfdcr %0, 0x0b2\n"
0195 ".machine \"pop\"" :
0196 "=r" (iocr)
0197 );
0198 iocr &=~0x800000;
0199 __asm__ volatile (
0200 ".machine \"push\"\n"
0201 ".machine \"any\"\n"
0202 "mtdcr 0x0b2, %0\n"
0203 ".machine \"pop\"" :
0204 "=r" (iocr) :
0205 "0" (iocr)
0206 );
0207
0208
0209
0210
0211 auto_restart = true;
0212 #endif
0213
0214 pit_value = rtems_configuration_get_microseconds_per_tick() *
0215 bsp_clicks_per_usec;
0216
0217
0218
0219
0220 __asm__ volatile ("mtspr 0x3db, %0" : : "r" (pit_value));
0221
0222
0223
0224
0225
0226 tick_time = get_itimer() + pit_value;
0227
0228 __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr)));
0229 tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000);
0230 #if 1
0231 __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr)));
0232 #endif
0233 }
0234
0235 static void Install_clock(void (*clock_isr)(void *))
0236 {
0237 rtems_irq_connect_data clockIrqConnData;
0238
0239 Clock_driver_ticks = 0;
0240
0241
0242
0243
0244
0245
0246
0247
0248 clockIrqConnData.on = ClockOn;
0249 clockIrqConnData.off = ClockOff;
0250 clockIrqConnData.isOn = ClockIsOn;
0251 clockIrqConnData.name = BSP_PIT;
0252 clockIrqConnData.hdl = clock_isr;
0253 if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) {
0254 printk("Unable to connect Clock Irq handler\n");
0255 rtems_fatal_error_occurred(1);
0256 }
0257
0258 atexit(Clock_exit);
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268 void Clock_exit(void)
0269 {
0270 rtems_irq_connect_data clockIrqConnData;
0271
0272 clockIrqConnData.name = BSP_PIT;
0273 if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) {
0274 printk("Unable to stop system clock\n");
0275 rtems_fatal_error_occurred(1);
0276 }
0277
0278 BSP_remove_rtems_irq_handler (&clockIrqConnData);
0279 }
0280
0281 void _Clock_Initialize( void )
0282 {
0283 Install_clock( Clock_isr );
0284 }