void fire( void ) { //fire REG[0] = FIRE; at91_tc_write ( & TC1_DESC, REG ); //pause wait( SEC ); wait( SEC ); //c**k REG[0] = C**K; at91_tc_write ( & TC1_DESC, REG ); }
int rt_request_timer (void (*handler)(void), unsigned tick, int use_apic) { unsigned long flags; flags = rtai_critical_enter(NULL); __ipipe_mach_timerstolen = 1; // no need to reprogram timer on timer_tick() call rt_times.tick_time = rtai_rdtsc(); rt_times.linux_tick = __ipipe_mach_ticks_per_jiffy; if (tick > 0) { rt_periodic = 1; /* Periodic setup -- Use the built-in Adeos service directly. */ if (tick > __ipipe_mach_ticks_per_jiffy) { tick = __ipipe_mach_ticks_per_jiffy; } rt_times.intr_time = rt_times.tick_time + tick; rt_times.linux_time = rt_times.tick_time + rt_times.linux_tick; rt_times.periodic_tick = tick; /* Prepare TCx to reload automaticly on RC compare */ at91_tc_write(AT91_TC_CCR, AT91_TC_CLKDIS); at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3 | AT91_TC_WAVESEL_UP_AUTO | AT91_TC_WAVE); at91_tc_write(AT91_TC_RC, rt_times.periodic_tick); at91_tc_write(AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG); } else { rt_periodic = 0; /* Oneshot setup. */ rt_times.intr_time = rt_times.tick_time + rt_times.linux_tick; rt_times.linux_time = rt_times.tick_time + rt_times.linux_tick; rt_times.periodic_tick = rt_times.linux_tick; /* Prepare TCx behaviour as oneshot timer */ at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3); rt_set_timer_delay(rt_times.periodic_tick); } rt_release_irq(RTAI_TIMER_IRQ); rt_request_irq(RTAI_TIMER_IRQ, (rt_irq_handler_t)handler, NULL, 0); extern_timer_isr = rtai_timer_handler; // shunt for ipipe.c __ipipe_grab_irq rtai_critical_exit(flags); return 0; }
//*---------------------------------------------------------------------------- //* Function Name : at91_tc_wait_open //* Object : Stop the ARM core during <microsec> us //* Input Parameters : <wait_desc> = Wait Descriptor pointer. //* Output Parameters : None //* Functions called : //*---------------------------------------------------------------------------- void at91_wait_open ( WaitDesc *wait_desc ) //* Begin { u_int clock_select ; u_int regs[4] ; switch ( wait_desc->mode ) { case WAIT_DELAY : case WAIT_NEXT_EVENT_MAX_DELAY : //* Startup the Timer Counter Channel at91_tc_open ( wait_desc->tc_desc, TC_WAVE | TC_CPCDIS, FALSE, FALSE) ; //* Compute and Setup register C for period depending on master clock regs[RA] = 0 ; regs[RC] = wait_desc->period ; //* Setup registers according master clock and required timings at91_tc_compute_microsec ( ®s[RC], &clock_select, wait_desc->mcki_khz ) ; regs[RB] = regs[RC] ; at91_tc_set_mode (wait_desc->tc_desc, clock_select, 1) ; at91_tc_write (wait_desc->tc_desc, regs ) ; //* Open the interrupt on the AIC at91_irq_open ( wait_desc->tc_desc->periph_id, 7, AIC_SRCTYPE_INT_EDGE_TRIGGERED, wait_desc->handler ) ; //* Enable the RC Compare interrupt wait_desc->tc_desc->tc_base->TC_IER = TC_CPCS ; //* Trig the timer at91_tc_trig_cmd ( wait_desc->tc_desc, TC_TRIG_CHANNEL ) ; break ; } switch ( wait_desc->mode ) { case WAIT_DELAY : case WAIT_NEXT_EVENT : //* Enter Idle Mode at91_clock_set_mode ( PS_MODE_IDLE ) ; break ; case WAIT_NEXT_EVENT_MAX_DELAY : //* While the Timer Counter hasn't reached the end while (( wait_desc->tc_desc->tc_base->TC_SR & TC_CPCS ) == 0 ) //* Enter Idle Mode at91_clock_set_mode ( PS_MODE_IDLE ) ; break ; } switch ( wait_desc->mode ) { case WAIT_DELAY : case WAIT_NEXT_EVENT_MAX_DELAY : //* Close the interrupt on the AIC at91_irq_close ( wait_desc->tc_desc->periph_id ) ; //* Close the Timer Counter Channel at91_tc_close ( wait_desc->tc_desc ); break ; } //* End }
void rt_free_timer (void) { unsigned long flags; rt_periodic = 0; __ipipe_mach_timerstolen = 0; // ipipe can reprogram timer for Linux now at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3); // back to oneshot mode rt_set_timer_delay(__ipipe_mach_ticks_per_jiffy); // regular timer delay rt_release_irq(RTAI_TIMER_IRQ); // free this irq rtai_save_flags_and_cli(flags); // critical section extern_timer_isr = NULL; // let ipipe run as normally rtai_restore_flags(flags); // end of critical section }
void servoInit(void) { u_int mode = TC_CLKS_MCK32 | TC_EEVT_XC0 | TC_CPCTRG | TC_WAVE | TC_ACPA_CLEAR_OUTPUT | TC_ACPC_SET_OUTPUT | TC_ASWTRG_SET_OUTPUT; //initialize/turn on servo at91_tc_open ( & TC1_DESC, mode, TRUE, FALSE ); at91_tc_write ( & TC1_DESC, REG ); at91_tc_trig_cmd ( & TC1_DESC, TC_TRIG_CHANNEL ); }
void __init at91x40_timer_init(void) { unsigned int v; at91_tc_write(AT91_TC_BCR, 0); v = at91_tc_read(AT91_TC_BMR); v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE; at91_tc_write(AT91_TC_BMR, v); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, AT91_TC_CLKDIS); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CMR, (AT91_TC_TIMER_CLOCK4 | AT91_TC_CPCTRG)); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_IDR, 0xffffffff); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_RC, (AT91X40_MASTER_CLOCK / 128) / HZ - 1); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_IER, (1<<4)); setup_irq(AT91X40_ID_TC1, &at91x40_timer_irq); at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN)); }
void at91_ipipe_init(struct clock_event_device *host_timer) { unsigned char tc_divisors[] = { 2, 8, 32, 128, 0, }; unsigned master_freq, divisor = 0, divided_freq = 0; unsigned long long wrap_ns; int tc_timer_clock; unsigned short v; struct clk *clk; #ifdef CONFIG_ARCH_AT91SAM9263 clk = clk_get(NULL, "tcb_clk"); #elif defined(CONFIG_ARCH_AT91SAM9G45) clk = clk_get(NULL, "tcb0_clk"); #else /* not AT91SAM9263 or AT91SAM9G45*/ clk = clk_get(NULL, "tc"__stringify(CONFIG_IPIPE_AT91_TC) "_clk"); #endif clk_enable(clk); /* Disable the channel */ at91_tc_write(AT91_TC_CCR, AT91_TC_CLKDIS); /* Disable all interrupts. */ at91_tc_write(AT91_TC_IDR, ~0ul); master_freq = clk_get_rate(clk_get(NULL, "mck")); /* Find the first frequency above 1 MHz */ for (tc_timer_clock = ARRAY_SIZE(tc_divisors) - 1; tc_timer_clock >= 0; tc_timer_clock--) { divisor = tc_divisors[tc_timer_clock]; divided_freq = (divisor ? master_freq / divisor : AT91_SLOW_CLOCK); if (divided_freq > 1000000) break; } wrap_ns = (unsigned long long) (AT91_TC_REG_MASK + 1) * NSEC_PER_SEC; do_div(wrap_ns, divided_freq); if (divided_freq < 1000000) printk(KERN_INFO "AT91 I-pipe warning: could not find a" " frequency greater than 1MHz\n"); printk(KERN_INFO "AT91 I-pipe timer: div: %u, freq: %u.%06u MHz, wrap: " "%u.%06u ms\n", divisor, divided_freq / 1000000, divided_freq % 1000000, (unsigned) wrap_ns / 1000000, (unsigned) wrap_ns % 1000000); /* Add a 1ms margin. It means that when an interrupt occurs, update_tsc must be called within 1ms. update_tsc is called by acktimer when no higher domain handles the timer, and called through set_dec when a higher domain handles the timer. */ wrap_ns -= 1000000; /* Set up the interrupt. */ if (host_timer && host_timer->features & CLOCK_EVT_FEAT_ONESHOT && host_timer->max_delta_ns > wrap_ns) host_timer->max_delta_ns = wrap_ns; /* No Sync. */ at91_tc_write(AT91_TC_BCR, 0); /* program NO signal on XCN */ v = readl((void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR)); v &= ~TCNXCNS(CONFIG_IPIPE_AT91_TC, 3); v |= TCNXCNS(CONFIG_IPIPE_AT91_TC, 1); /* AT91_TC_TCNXCNS_NONE */ writel(v, (void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR)); /* Use the clock selected as input clock. */ at91_tc_write(AT91_TC_CMR, tc_timer_clock); /* Load the TC register C. */ write_RC(0xffff); /* Enable the channel. */ at91_tc_write(AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG); at91_itimer.freq = divided_freq; at91_itimer.min_delay_ticks = ipipe_timer_ns2ticks(&at91_itimer, 2000); max_delta_ticks = ipipe_timer_ns2ticks(&at91_itimer, wrap_ns); ipipe_timer_register(&at91_itimer); tsc_info.freq = divided_freq; __ipipe_tsc_register(&tsc_info); at91_pic_muter_register(); }
static void at91_tc_release(struct ipipe_timer *timer) { /* Disable all interrupts. */ at91_tc_write(AT91_TC_IDR, ~0ul); }
static void at91_tc_request(struct ipipe_timer *timer, int steal) { /* Enable CPCS interrupt. */ at91_tc_write(AT91_TC_IER, AT91_TC_CPCS); }