Hello!
I am trying to use level triggered interrupts on my Intel Atom E3800 based board. A GPIO pin, wich I want to use is
GPIO_S5[13]. So This GPIO is located in Intel Legacy Block (iLB) and registers, wich correspond to this GPIO, are mapped
to memory (not to legacy space). To configure this GPIO I made the follows:
...
pci_attach( 0 );
//Find the PCI/ISA bus (intel legacy block)
pci_find_class(0x060100, 0, &busnum, &devfuncnum);
//Get IOBASE register, which contains base address for memory mapped GPIOs registers (GPSSUS) accoding to datasheet
pci_read_config32(busnum, devfuncnum, 0x4C, 1, &ioBaseRegister);
uint32_t ioControllerBaseAddr = ioBaseRegister & 0xFFFFC000;
//Get pad configuration register for GPIO_S5[13]
uint64_t s5_13_pad_config = (ioControllerBaseAddr + 0x2000 + 0x140);
uint32_t * ptr = (uint32_t*) mmap_device_memory( 0, 4, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, s5_13_pad_config );
// (1<<26) - Set Gb Tne to 1 ( Detect falling edge. For level interrupt mode it will enable active low level irq)
// (1<<27) - Set Direct Irq En (direct_irq_en)
// (1<<24) - Set Gd Level (gd_level): When this bit is set a level irq will be choose and not edge irq
*ptr |= (1<<26)|(1<<27)|(1<<24);
//Get pad value register for GPIO_S5[13]
uint64_t s5_13_pad_val_unmaped = (ioControllerBaseAddr + 0x2000 + 0x148);
ptr = (uint32_t*) mmap_device_memory( 0, 4, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, s5_13_pad_val_unmaped );
//Enable input, disable output
*ptr |= (1<<1);
*ptr &= ~(1<<2);
//Connect gpios5[13] to IRQ0 (APIC 67)
uint64_t direct_irq0 = (ioControllerBaseAddr + 0x2000 + 0x980);
ptr = (uint32_t*) mmap_device_memory( 0, 4, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, direct_irq0 );
*ptr &= ~(0x7F);
*ptr |= 13;
pci_detach( phdl )
...
In my startup-apic -vv output a see:
...
[13] vec: 67, cpumask:00000001, ID: 2, busid:0, busintr:13, dest intin:13, type:0, flags:00000005
...
So when I am waiting for interrupt I do the follows:
struct sigevent int_event;
static int int_counter;
const struct sigevent *handler (void *area, int id) {
int_counter++;
return (&int_event);
}
void * interruptWaitThread( void* arg )
{
ThreadCtl( _NTO_TCTL_IO, 0 );
struct sigevent event;
int_event.sigev_notify = SIGEV_INTR;
InterruptAttach( 13, &handler, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK);
while (1)
{
InterruptWait (0, NULL);
printf (" Got interrupt %lu ( 0x%lX ) #%4ld\n", 13, 13, int_counter);
}
return( 0 );
}
But the interruptWaitThread have never unblocked from InterruptWait(). What am doing wrong?
Regards,
Vasily.