4700 interrupts: Difference between revisions

From embeddedTS Manuals
(Created page with "We include a userspace IRQ patch in our kernels. This allows you to receive interrupts from your applications where you would normally have to write a kernel driver. This wo...")
 
m (FTP links auto-updated (https://www.marvell.com/application-processors/armada-100/assets/armada_16x_software_manual.pdf →‎ https://www.marvell.com/content/dam/marvell/en/public-collateral/application-processors/marvell-application-processors-armada-16x-software-manual-2010-11.pdf))
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
We include a userspace IRQ patch in our kernels.  This allows you to receive interrupts from your applications where you would normally have to write a kernel driver.  This works by creating a file for each interrupt in '/proc/irq/<irqnum>/irq'.  The new irq file allows you to block on a read on the file until an interrupt fires.
{{:TS-4700 Interrupts overview}}
 
The original patch is documented [http://lwn.net/Articles/127293/ here].
 
The Linux kernel on the TS-4700 supports up to 16 IRQs from the FPGA.  When the CPU receives an IRQ from the FPGA, it uses the IRQ register in the [[#Syscon]] to find out which IRQ on the MUX is triggering. Currently only three IRQs are used. Off-board IRQs 5, 6, and 7 correspond to FPGA IRQs 0, 1, and 2, respectively.  FPGA IRQs 3 to 15 are reserved for future uses.  If the DIO pins are not being used as IRQs, they can be masked out by writing 0 to the corresponding bit in the IRQ mask register.


{| class="wikitable"
{| class="wikitable"
Line 14: Line 10:
| Combined GPIO Interrupt  
| Combined GPIO Interrupt  
| Any MFP pin
| Any MFP pin
|-
| 64
| XUART IRQ
| N/A
|-
| 65
| CAN1 IRQ
| N/A
|-
| 66
| CAN 2 IRQ
| N/A
|-
|-
| 67
| 67
| IRQ5/DIO_00
| IRQ5/DIO_00<ref name=MUXBUSIRQ>The PC/104 IRQs need to have the [[#MUXBUS|MUXBUS]] bus enabled in order to function as IRQs</ref>
| CN1-93
| CN1-93
|-
|-
| 68
| 68
| IRQ6/DIO_01
| IRQ6/DIO_01<ref name=MUXBUSIRQ />
| CN1-91
| CN1-91
|-
|-
| 69
| 69
| IRQ7/DIO_02
| IRQ7/DIO_02<ref name=MUXBUSIRQ />
| CN1-89
| CN1-89
|-
| 70
| [[#Event Driven GPIO|EVGPIO]]
| N/A
|}
|}
<references />


This example below will work with any of our TS-Socket boards running Linux.  This opens the IRQ number specified in the first argument and prints when it detects an IRQ.
{{:TS-4700 Interrupts example code}}
 
<source lang=c>
#include <stdio.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
 
int main(int argc, char **argv)
{
char proc_irq[32];
int ret, irqfd = 0;
int buf; // Holds irq junk data
fd_set fds;
 
if(argc < 2) {
printf("Usage: %s <irq number>\n", argv[0]);
return 1;
}
 
snprintf(proc_irq, sizeof(proc_irq), "/proc/irq/%d/irq", atoi(argv[1]));
irqfd = open(proc_irq, O_RDONLY| O_NONBLOCK, S_IREAD);
 
if(irqfd == -1) {
printf("Could not open IRQ %s\n", argv[1]);
return 1;
}
while(1) {
FD_SET(irqfd, &fds); //add the fd to the set
// See if the IRQ has any data available to read
ret = select(irqfd + 1, &fds, NULL, NULL, NULL);
if(FD_ISSET(irqfd, &fds))
{
FD_CLR(irqfd, &fds);  //Remove the filedes from set
printf("IRQ detected\n");
// Clear the junk data in the IRQ file
read(irqfd, &buf, sizeof(buf));
}
//Sleep, or do any other processing here
usleep(10000);
}
return 0;
}
</source>


Any of the MFP pins can be repurposed to trigger IRQ 49.  For example, to make MFP_46 (CN2_72) trigger on a rising edge:
Any of the MFP pins can be repurposed to trigger IRQ 49.  For example, to make MFP_46 (CN2_72) trigger on a rising edge:
Line 91: Line 55:
</source>
</source>


The IRQ numbers 67-69 are muxed IRQs which are only enabled when using the [[#MUXBUS]].  You can enable these by running these commands:
See page 169 of the [https://www.marvell.com/content/dam/marvell/en/public-collateral/application-processors/marvell-application-processors-armada-16x-software-manual-2010-11.pdf CPU manual] for more information on the interrupt controller.
<source lang=bash>
# If you're in Debian you need this next line
# source /initrd/ts4700.subr
pc104on
</source>
This will repurpose other DIO for the [[#MUXBUS]] data, address, and bus control lines as well.
 
See page 169 of the [http://www.marvell.com/application-processors/armada-100/assets/armada_16x_software_manual.pdf CPU manual] for more information on the interrupt controller.

Latest revision as of 16:30, 15 January 2021

We include a userspace IRQ patch in our kernels. This allows you to receive interrupts from your applications where you would normally have to write a kernel driver. This works by creating a file for each interrupt in '/proc/irq/<irqnum>/irq'. The new irq file allows you to block on a read on the file until an interrupt fires.

The original patch is documented here.

The Linux kernel supports up to 16 IRQs from the FPGA. When the CPU receives an IRQ from the FPGA, it uses the IRQ register in the #Syscon to find out which IRQ on the MUX is triggering. Currently only three IRQs are used. Off-board IRQs 5, 6, and 7 correspond to FPGA IRQs 0, 1, and 2, respectively. FPGA IRQs 3 to 15 are reserved for future uses. If the DIO pins are not being used as IRQs, they can be masked out by writing 0 to the corresponding bit in the IRQ mask register.

IRQ # Name Socket Location
49 Combined GPIO Interrupt Any MFP pin
64 XUART IRQ N/A
65 CAN1 IRQ N/A
66 CAN 2 IRQ N/A
67 IRQ5/DIO_00[1] CN1-93
68 IRQ6/DIO_01[1] CN1-91
69 IRQ7/DIO_02[1] CN1-89
70 EVGPIO N/A
  1. 1.0 1.1 1.2 The PC/104 IRQs need to have the MUXBUS bus enabled in order to function as IRQs

This example below will work with any of our products that support userspace IRQs. It opens the IRQ number specified in the first argument, and prints when it detects an IRQ.

#include <stdio.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	char proc_irq[32];
	int ret, irqfd = 0;
	int buf; // Holds irq junk data
	fd_set fds;

	if(argc < 2) {
		printf("Usage: %s <irq number>\n", argv[0]);
		return 1;
	}

	snprintf(proc_irq, sizeof(proc_irq), "/proc/irq/%d/irq", atoi(argv[1]));
	irqfd = open(proc_irq, O_RDONLY| O_NONBLOCK, S_IREAD);

	if(irqfd == -1) {
		printf("Could not open IRQ %s\n", argv[1]);
		return 1;
	}
	
	while(1) {
		FD_SET(irqfd, &fds); //add the fd to the set
		// See if the IRQ has any data available to read
		ret = select(irqfd + 1, &fds, NULL, NULL, NULL);
		
		if(FD_ISSET(irqfd, &fds))
		{
			FD_CLR(irqfd, &fds);  //Remove the filedes from set
			printf("IRQ detected\n");
			
			// Clear the junk data in the IRQ file
			read(irqfd, &buf, sizeof(buf));
		}
		
		//Sleep, or do any other processing here
		usleep(10000);
	}
	
	return 0;
}

Any of the MFP pins can be repurposed to trigger IRQ 49. For example, to make MFP_46 (CN2_72) trigger on a rising edge:

# Enable rising edge detection on MFP_46
peekpoke 32 0xD4019034 0x4000

# Unmask MFP_46
peekpoke 32 0xD40190A0 0x4000

# to clear the interrupt after it has been triggered
peekpoke 32 0xD401904c 0x4000

See page 169 of the CPU manual for more information on the interrupt controller.