Controlling GPIO Inputs and Outputs in Zynq-7000 Linux Kernel Modules

Kernel Space GPIO Manipulation

For the FMQL45T900 platform based on the Zynq-7000 architecture, controlling pins from the kernel space requires determining the correct GPIO index. When utilizing EMIO5 exported from Vivado, the corresponding system GPIO number calculates to 431. The device tree mapping for this pin appears as <&portc 5 0x01>.

Module Compilation Setup

Adjust the kernel source directory in the Makefile according to your build environment before compiling the kernel object.

obj-m += zynq_pin_ctrl.o

KDIR ?= /home/FMQL-Linux-SDK-Prj/linux-4.14.55-fmsh

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

Standard Kernel GPIO API

The Linux kernel provides a standard set of functions for pin manipulation:

API FunctionParametersDescription
gpio_is_validpin numberChecks if the GPIO index is valid
gpio_requestpin number, labelAllocates the GPIO for exclusive use
gpio_direction_inputpin numberSets the pin direction to input
gpio_get_valuepin numberReads the current logic level
gpio_direction_outputpin number, default valueSets the pin direction to output
gpio_set_valuepin number, logic levelDrives the pin to the specified level

Driver Implementation Example

The following snippet demonstrates allocating the pin, configuring it as an output, driving it high, reconfiguring it as an input, and reading its state:

/*
 * Target: FMQL45T900
 * Test Pin: EMIO5
 * DT entry: <&portc 5 0x01>
 */
#define MODULE_TAG "zynq_gpio_dev"
#define PIN_ID 431 // EMIO5

int setup_pin(int pin) {
    int ret_val, pin_state;

    if (!gpio_is_valid(pin)) {
        pr_err("Invalid GPIO specified\n");
        return -ENODEV;
    }

    ret_val = gpio_request(pin, "emio_test_pin");
    if (ret_val) {
        pr_err("GPIO allocation failed\n");
        return ret_val;
    }

    // Configure as output initially
    ret_val = gpio_direction_output(pin, 0);
    if (ret_val) {
        pr_err("Failed to configure as output\n");
        gpio_free(pin);
        return ret_val;
    }

    gpio_set_value(pin, 1); // Drive high
    pr_info("%s: Pin driven HIGH\n", MODULE_TAG);

    // Switch to input and read
    ret_val = gpio_direction_input(pin);
    if (ret_val) {
        pr_err("Failed to reconfigure as input\n");
        gpio_free(pin);
        return ret_val;
    }

    pin_state = gpio_get_value(pin);
    pr_info("%s: Pin state read as %d\n", MODULE_TAG, pin_state);

    gpio_free(pin);
    return 0;
}

Module Deployment

Load the compiled module into the running kernel:

insmod zynq_pin_ctrl.ko

Remove the module from the kernel:

rmmod zynq_pin_ctrl

Tags: Zynq-7000 Linux Kernel Driver gpio FMQL45T900 Embedded Systems

Posted on Wed, 09 Sep 2026 16:05:36 +0000 by Bike Racer