81 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
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)
 | 
						|
 |