| README on the Vectored Interrupt Controller of the LH7A404 | |
| ========================================================== | |
| The 404 revision of the LH7A40X series comes with two vectored | |
| interrupts controllers. While the kernel does use some of the | |
| features of these devices, it is far from the purpose for which they | |
| were designed. | |
| When this README was written, the implementation of the VICs was in | |
| flux. It is possible that some details, especially with priorities, | |
| will change. | |
| The VIC support code is inspired by routines written by Sharp. | |
| Priority Control | |
| ---------------- | |
| The significant reason for using the VIC's vectoring is to control | |
| interrupt priorities. There are two tables in | |
| arch/arm/mach-lh7a40x/irq-lh7a404.c that look something like this. | |
| static unsigned char irq_pri_vic1[] = { IRQ_GPIO3INTR, }; | |
| static unsigned char irq_pri_vic2[] = { | |
| IRQ_T3UI, IRQ_GPIO7INTR, | |
| IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, }; | |
| The initialization code reads these tables and inserts a vector | |
| address and enable for each indicated IRQ. Vectored interrupts have | |
| higher priority than non-vectored interrupts. So, on VIC1, | |
| IRQ_GPIO3INTR will be served before any other non-FIQ interrupt. Due | |
| to the way that the vectoring works, IRQ_T3UI is the next highest | |
| priority followed by the other vectored interrupts on VIC2. After | |
| that, the non-vectored interrupts are scanned in VIC1 then in VIC2. | |
| ISR | |
| --- | |
| The interrupt service routine macro get_irqnr() in | |
| arch/arm/kernel/entry-armv.S scans the VICs for the next active | |
| interrupt. The vectoring makes this code somewhat larger than it was | |
| before using vectoring (refer to the LH7A400 implementation). In the | |
| case where an interrupt is vectored, the implementation will tend to | |
| be faster than the non-vectored version. However, the worst-case path | |
| is longer. | |
| It is worth noting that at present, there is no need to read | |
| VIC2_VECTADDR because the register appears to be shared between the | |
| controllers. The code is written such that if this changes, it ought | |
| to still work properly. | |
| Vector Addresses | |
| ---------------- | |
| The proper use of the vectoring hardware would jump to the ISR | |
| specified by the vectoring address. Linux isn't structured to take | |
| advantage of this feature, though it might be possible to change | |
| things to support it. | |
| In this implementation, the vectoring address is used to speed the | |
| search for the active IRQ. The address is coded such that the lowest | |
| 6 bits store the IRQ number for vectored interrupts. These numbers | |
| correspond to the bits in the interrupt status registers. IRQ zero is | |
| the lowest interrupt bit in VIC1. IRQ 32 is the lowest interrupt bit | |
| in VIC2. Because zero is a valid IRQ number and because we cannot | |
| detect whether or not there is a valid vectoring address if that | |
| address is zero, the eigth bit (0x100) is set for vectored interrupts. | |
| The address for IRQ 0x18 (VIC2) is 0x118. Only the ninth bit is set | |
| for the default handler on VIC1 and only the tenth bit is set for the | |
| default handler on VIC2. | |
| In other words. | |
| 0x000 - no active interrupt | |
| 0x1ii - vectored interrupt 0xii | |
| 0x2xx - unvectored interrupt on VIC1 (xx is don't care) | |
| 0x4xx - unvectored interrupt on VIC2 (xx is don't care) | |