File indexing completed on 2025-05-11 08:23:52
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
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 #include <rtems.h>
0058 #include <bsp/gtreg.h>
0059 #include <libcpu/io.h>
0060 #include <bsp.h>
0061 #include <bsp/irq.h>
0062 #include <rtems/bspIo.h>
0063
0064 #include <stdint.h>
0065
0066 #include <bsp/gt_timer.h>
0067
0068 #define DEBUG
0069
0070 static inline uint32_t gt_rd(uint32_t off)
0071 {
0072 return in_le32( (volatile uint32_t *)(BSP_MV64x60_BASE+off) );
0073 }
0074
0075 static inline void gt_wr(uint32_t off, uint32_t val)
0076 {
0077 out_le32( (volatile uint32_t *)(BSP_MV64x60_BASE+off), val);
0078 }
0079
0080 static inline uint32_t gt_timer_bitmod(uint32_t off, uint32_t clr, uint32_t set)
0081 {
0082 unsigned flags;
0083 uint32_t rval;
0084
0085 rtems_interrupt_disable(flags);
0086 rval = gt_rd( off );
0087 gt_wr( off, (rval & ~clr) | set );
0088 rtems_interrupt_enable(flags);
0089 return rval;
0090 }
0091
0092 #define GT_TIMER_MAX 3
0093 #define TIMER_ARGCHECK(t) do { if ((t)>GT_TIMER_MAX) return -1; } while (0)
0094
0095 static struct {
0096 void (*isr)(void *);
0097 void *arg;
0098 } gt_timer_isrs[GT_TIMER_MAX+1] = {{0},};
0099
0100 uint32_t BSP_timer_read(uint32_t timer)
0101 {
0102 TIMER_ARGCHECK(timer);
0103 return gt_rd(GT_TIMER_0 + (timer<<2));
0104 }
0105
0106 int
0107 BSP_timer_start(uint32_t timer, uint32_t period)
0108 {
0109 TIMER_ARGCHECK(timer);
0110 gt_wr(GT_TIMER_0 + (timer<<2), period);
0111 return 0;
0112 }
0113
0114 int
0115 BSP_timer_stop(uint32_t timer)
0116 {
0117 TIMER_ARGCHECK(timer);
0118
0119 gt_timer_bitmod(GT_TIMER_0_3_Ctl, GT_TIMER_0_Ctl_Enb << (timer<<3), 0);
0120 gt_wr(GT_TIMER_0 + (timer<<2), 0);
0121 gt_timer_bitmod(GT_TIMER_0_3_Ctl, 0, GT_TIMER_0_Ctl_Enb << (timer<<3));
0122 return 0;
0123 }
0124
0125 int
0126 BSP_timer_setup(uint32_t timer, void (*isr)(void *arg), void *arg, int reload)
0127 {
0128 TIMER_ARGCHECK(timer);
0129 if ( isr && gt_timer_isrs[timer].isr )
0130 return -1;
0131
0132 BSP_timer_stop(timer);
0133
0134 gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, GT_TIMER_0_Intr<<timer, 0);
0135 gt_timer_bitmod(GT_TIMER_0_3_Intr_Cse, GT_TIMER_0_Intr<<timer, 0);
0136
0137
0138 if ( reload )
0139 gt_timer_bitmod(GT_TIMER_0_3_Ctl, 0, GT_TIMER_0_Ctl_Rld << (timer<<3));
0140 else
0141 gt_timer_bitmod(GT_TIMER_0_3_Ctl, GT_TIMER_0_Ctl_Rld << (timer<<3), 0);
0142
0143 asm volatile("":::"memory");
0144
0145 if ( isr ) {
0146 gt_timer_isrs[timer].isr = isr;
0147 gt_timer_isrs[timer].arg = arg;
0148 asm volatile("":::"memory");
0149 gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, 0, GT_TIMER_0_Intr<<timer);
0150 } else {
0151 gt_timer_isrs[timer].isr = 0;
0152 gt_timer_isrs[timer].arg = 0;
0153 }
0154 return 0;
0155 }
0156
0157 static void
0158 gt_timer_hdl(rtems_irq_hdl_param arg)
0159 {
0160 int iarg = (int)arg;
0161 int timer;
0162 uint32_t bit;
0163
0164 for ( ; iarg; iarg >>= 4 ) {
0165 timer = (iarg & 0xf)-1;
0166 bit = GT_TIMER_0_Intr<<timer;
0167 if ( gt_timer_bitmod(GT_TIMER_0_3_Intr_Cse, bit, 0) & bit ) {
0168
0169 if ( ! gt_timer_isrs[timer].isr ) {
0170 printk("gt_timer: warning; no ISR connected but and IRQ happened (timer # %i)\n", timer);
0171
0172 gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, bit, 0);
0173 } else {
0174 gt_timer_isrs[timer].isr(gt_timer_isrs[timer].arg);
0175 }
0176 }
0177 }
0178 }
0179
0180 int
0181 BSP_timers_initialize(void)
0182 {
0183 rtems_irq_connect_data xx = {0};
0184 int i, ainc, arg;
0185
0186 xx.hdl = gt_timer_hdl;
0187 xx.on = 0;
0188 xx.off = 0;
0189 xx.isOn = 0;
0190
0191 switch (BSP_getDiscoveryVersion(0)) {
0192 case MV_64360:
0193 i = 3;
0194 ainc = 1;
0195 arg = 4;
0196 break;
0197 default:
0198 i = 1;
0199 ainc = 0x0202;
0200 arg = 0x0403;
0201 break;
0202 }
0203
0204 for ( ; i>=0; i--, arg-=ainc ) {
0205 xx.name = BSP_IRQ_TIME0_1 + i;
0206 xx.handle = (rtems_irq_hdl_param)arg;
0207 if ( !BSP_install_rtems_irq_handler(&xx) )
0208 return -1;
0209 }
0210
0211 return 0;
0212 }
0213
0214 #ifdef DEBUG_MODULAR
0215 static int
0216 BSP_timers_uninstall(void)
0217 {
0218 rtems_irq_connect_data xx = {0};
0219 int i;
0220
0221 xx.hdl = gt_timer_hdl;
0222 xx.on = 0;
0223 xx.off = 0;
0224 xx.isOn = 0;
0225
0226 for ( i=0; i<= GT_TIMER_MAX; i++ ) {
0227 if ( BSP_timer_setup(i, 0, 0, 0) )
0228 return -1;
0229 }
0230
0231 switch (BSP_getDiscoveryVersion(0)) {
0232 case MV_64360:
0233 i = 3;
0234 break;
0235 default:
0236 i = 1;
0237 break;
0238 }
0239
0240 for ( ; i >= 0; i-- ) {
0241 xx.name = BSP_IRQ_TIME0_1 + i;
0242 BSP_get_current_rtems_irq_handler(&xx);
0243 if ( !BSP_remove_rtems_irq_handler(&xx) )
0244 return -1;
0245 }
0246
0247 return 0;
0248 }
0249 #endif
0250
0251 uint32_t
0252 BSP_timer_clock_get(uint32_t timer)
0253 {
0254 return BSP_bus_frequency;
0255 }
0256
0257 int BSP_timer_instances(void)
0258 {
0259 return GT_TIMER_MAX + 1;
0260 }
0261
0262
0263
0264
0265
0266 static uint32_t wdog_on = 0x00ffffff;
0267
0268 static uint32_t rd_wdcnf(void)
0269 {
0270 uint32_t cnf = gt_rd(GT_WDOG_Config);
0271
0272
0273
0274
0275
0276
0277 if ( ~0 == cnf )
0278 cnf = wdog_on;
0279 return cnf;
0280 }
0281
0282
0283 static void dog_toggle(uint32_t ctl)
0284 {
0285 ctl &= ~( GT_WDOG_Config_Ctl1a | GT_WDOG_Config_Ctl1b \
0286 | GT_WDOG_Config_Ctl2a | GT_WDOG_Config_Ctl2b);
0287 gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl1a);
0288 gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl1b);
0289 }
0290
0291 static void dog_pet(uint32_t ctl)
0292 {
0293 ctl &= ~( GT_WDOG_Config_Ctl1a | GT_WDOG_Config_Ctl1b \
0294 | GT_WDOG_Config_Ctl2a | GT_WDOG_Config_Ctl2b);
0295 gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl2a);
0296 gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl2b);
0297 }
0298
0299
0300
0301
0302
0303
0304
0305
0306 int
0307 BSP_watchdog_enable(uint32_t timeout_us)
0308 {
0309 unsigned long long x = timeout_us;
0310 unsigned flags;
0311 uint32_t ctl;
0312
0313 x *= BSP_bus_frequency;
0314 x /= 256;
0315 x /= 1000000;
0316
0317 if ( x > (1<<24)-1 )
0318 x = (1<<24)-1;
0319
0320 if ( 0xffffffff != timeout_us )
0321 timeout_us = x;
0322
0323 rtems_interrupt_disable(flags);
0324
0325 ctl = rd_wdcnf();
0326
0327
0328 if ( GT_WDOG_Config_Enb & ctl ) {
0329 dog_toggle(ctl);
0330 }
0331 if ( 0xffffffff == timeout_us ) {
0332 timeout_us = ctl & ((1<<24)-1);
0333 dog_toggle(ctl);
0334 dog_pet(ctl);
0335 } else {
0336 gt_wr(GT_WDOG_Config, timeout_us | GT_WDOG_Config_Ctl1a);
0337 gt_wr(GT_WDOG_Config, timeout_us | GT_WDOG_Config_Ctl1b);
0338 }
0339
0340 wdog_on = GT_WDOG_Config_Enb | timeout_us;
0341
0342 rtems_interrupt_enable(flags);
0343 return 0;
0344 }
0345
0346
0347
0348
0349 int BSP_watchdog_disable(void)
0350 {
0351 unsigned long flags;
0352 uint32_t ctl;
0353
0354 rtems_interrupt_disable(flags);
0355
0356 ctl = rd_wdcnf();
0357
0358 if ( (GT_WDOG_Config_Enb & ctl) ) {
0359 dog_toggle(ctl);
0360 wdog_on = ctl & ~(GT_WDOG_Config_Enb);
0361 }
0362
0363 rtems_interrupt_enable(flags);
0364 return 0;
0365 }
0366
0367
0368
0369
0370
0371
0372 int BSP_watchdog_status(void)
0373 {
0374 uint32_t ctl = rd_wdcnf();
0375
0376
0377 return GT_WDOG_Config_Enb & ctl ? ctl : 0;
0378 }
0379
0380
0381
0382
0383
0384 int BSP_watchdog_pet(void)
0385 {
0386 unsigned long flags;
0387
0388 if ( !wdog_on )
0389 return -1;
0390 rtems_interrupt_disable(flags);
0391 dog_pet(rd_wdcnf());
0392 rtems_interrupt_enable(flags);
0393 return 0;
0394 }
0395
0396
0397 #ifdef DEBUG_MODULAR
0398 int
0399 _cexpModuleFinalize(void *unused)
0400 {
0401 BSP_watchdog_disable();
0402 return BSP_timers_uninstall();
0403 }
0404
0405 void
0406 _cexpModuleInitialize(void *unused)
0407 {
0408 BSP_timers_initialize();
0409 }
0410 #endif