Configuring GPIO Interrupt Input in Linux for Zynq-7000 and FMQL45T900 Platforms

The example presented here demonstrates how to configure an interrupt-based GPIO enput within the Linux kernel driver for FMQL45T900, which shares similarities with Zynq-7000 platforms.

To begin, determine the correct GPIO number corresponding to the physical pin. For instance, EMIO5 maps to GPIO number 431 on the FMQL45T900 platform. In Vivado, enable EMIO configuration, expand it to 64 bits, and export the required pins externally by generating the top-level wrapper.

Below is the device tree reference and macro definitions used:

/*
Test Pin Configuration
FMQL45T900
EMIO5
Device Tree Entry:
<&portc 5 0x01>;
*/
#define DEV_NAME   "gpio"
#define GPIO_NUM   431 // Corresponds to EMIO5

A typical Makefile for building the kernel module might look like this (ensure KERN_DIR points to your kernel source):

ifneq ($(KERNELRELEASE),)
    obj-m := gpio_irq.o
else 
    KERN_DIR = /home/FMQL-Linux-SDK-Prj-20220223/linux-4.14.55-fmsh
all:
	make -C $(KERN_DIR) M=$(shell pwd) modules 
clean:
	make -C $(KERN_DIR) M=$(shell pwd) modules clean
	rm -rf modules.order
endif

Key GPIO and interrupt handling functions used in the driver include:

Function Parameters Description
gpio_is_valid GPIO number Validates GPIO availability
gpio_request GPIO number Requests control of GPIO
gpio_direction_input GPIO number Sets GPIO as input
gpio_get_value GPIO number Reads current value
gpio_direction_output GPIO number, value Configures GPIO as output
gpio_set_value GPIO number, value Writes specified level
gpio_to_irq GPIO number Maps GPIO to IRQ line
request_irq IRQ number, handler, flags Registers interrupt handler
free_irq IRQ number Releases registered IRQ
gpio_free GPIO number Releases GPIO resource

Sample initialization sequence within the driver:

if (!gpio_is_valid(gpio_num)) {
    printk(KERN_ERR "Invalid GPIO number\n");
    return -EINVAL;
}

printk(KERN_INFO "Using GPIO%d\n", gpio_num);

ret = gpio_request(gpio_num, "interrupt_gpio");
if (ret < 0) {
    printk(KERN_ERR "Cannot request GPIO%d\n", gpio_num);
    return ret;
}

ret = gpio_direction_input(gpio_num);
if (ret < 0) {
    printk(KERN_ERR "Failed to set direction for GPIO%d\n", gpio_num);
    goto fail_dir;
}

int initial_level = gpio_get_value(gpio_num);
printk(KERN_INFO DEV_NAME " Initial state: %d\n", initial_level);

unsigned int irq_line = gpio_to_irq(gpio_num);
printk(KERN_INFO "Mapped to IRQ line %d\n", irq_line);

ret = request_irq(irq_line,
                  gpio_interrupt_handler,
                  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                  "gpio_interrupt",
                  NULL);
if (ret < 0) {
    printk(KERN_ERR "Unable to register IRQ handler\n");
    goto fail_irq;
}
...
return 0;

fail_irq:
    gpio_free(gpio_num);
fail_dir:
    return ret;

After compiling the module using make, load it into the kernel with:

insmod gpio_irq.ko

Tags: Zynq-7000 FMQL45T900 Linux Driver GPIO Interrupt Embedded Systems

Posted on Thu, 13 Aug 2026 16:38:18 +0000 by mkohan