Hello,
I am using the GP timers on DM8168 to toggle a GPIO output in a given pattern (IR signal).
I have written a kernel module to do this, but have one remaining issue.
Sometimes the interrupt routine is being called TWICE per timer overflow interrupt. I suspect this might be because the INT clear write has not happened by the time I exit the interrupt routine, thus it fires again immediately.
I have tried reading back the interrupt enable register in the IRQ, but this didn't help.
The hw pointer is declared using ioremap_nocache, so it shouldn't be cached.
Any ideas?
BTW, the dmtimer routines do NOT work properly on dm8168. Because of this, I am controlling the HW regs directly.
Code:
static irqreturn_t timer_irq_handler(int irq, void *dev_id)
{
int ret;
// reset the timer interrupt status
//omap_dm_timer_write_status(timer_ptr, OMAP_TIMER_INT_OVERFLOW);
//omap_dm_timer_read_status(timer_ptr); // YES, you really need to do this 'wasteful' read
vsir_timer1[0x28>>2]=0x2;
ret = vsir_timer1[0x28>>2];
if (ret != 0){
// repeat clear
vsir_timer1[0x28>>2]=0x2;
}
//omap_writew(0x2, vsir_timer_base+0x28);
//ret = omap_readw(vsir_timer_base+0x28);
//printk("TIMER FIRED idx:%d cnt:%d",vsir_index,vsir_count);
// set GPIO
// use set/clear registers
// GPIO0 set 0x48032194
// GPIO0 clear 0x48032190
// based on output variable
if (((vsir_count%2)==0)&&((vsir_index%2)==0)){
//gpio_set_value(outp,1);
//writel(outp, vsir_gpio + 0x4);
vsir_gpio[(0x194)>>2] = outp;
//omap_writew(outp, GPIO_BASE);
}else{
//gpio_set_value(outp,0);
vsir_gpio[(0x190)>>2] = outp;
//omap_writew(outp, GPIO_BASE + 4);
}
// inc timer count
vsir_count -= 1;
if (vsir_count <=0){
// get next sequence
vsir_index++;
if (vsir_index < time_max){
vsir_count = time_arr[vsir_index];
}else if ((vsir_repeat>1)){
// restart
vsir_index=0;
vsir_count = time_arr[vsir_index];
if (vsir_repeat<999){vsir_repeat--;}
}else{
vsir_stop_timers();
}
}
// tell the kernel it's handled
return IRQ_HANDLED;
}