Home » Linux Kernel » Core Kernel » Understanding Linux Kernel GPIO APIs: A Comprehensive Guide for Beginners

Understanding Linux Kernel GPIO APIs: A Comprehensive Guide for Beginners

General-Purpose Input/Output (GPIO) is a critical feature in embedded systems and hardware interfacing. In Linux, the GPIO API allows users and developers to control and manage GPIO pins from both user space and kernel space. Whether you’re working with sensors, LEDs, or other peripherals, understanding how to use the Linux Kernel GPIO API is essential for interacting with hardware.

In this guide, we will walk through the basics of the Linux kernel’s GPIO subsystem, covering the key functions, how to interact with GPIOs in kernel drivers, and provide clear examples to help you get started.


What is GPIO?

A GPIO pin is a physical interface between a microcontroller or processor and other hardware components. GPIOs can be configured either as input (to read data from a sensor or switch) or output (to control LEDs or relays). GPIOs can also trigger interrupts based on signal changes, enabling real-time responses to hardware events.


Linux GPIO Subsystem

In the Linux kernel, the GPIO subsystem provides a standardized interface for managing GPIOs, regardless of the underlying hardware platform. This means that developers can write GPIO code in a platform-agnostic manner, making their drivers portable across different devices.

The Linux GPIO API consists of two main layers:

  1. User Space GPIO Interface (via /sys/class/gpio)
  2. Kernel Space GPIO API (for use in device drivers)

In this post, we will focus on the Kernel Space GPIO API, which is used when writing Linux kernel drivers.


Key Functions of the Linux Kernel GPIO API

The Linux Kernel GPIO API provides several functions to manage GPIO pins, from requesting a pin to setting its direction and value.

1. gpio_request()

Before using a GPIO pin, it must be requested by the driver. This function reserves a GPIO pin and ensures no other driver or part of the system can access it.

int gpio_request(unsigned int gpio, const char *label);
  • gpio: The GPIO pin number to be requested.
  • label: A human-readable name for the GPIO (e.g., “led” or “button”).

Example:

gpio_request(17, "my_led_gpio");

2. gpio_direction_input() and gpio_direction_output()

After requesting the GPIO pin, its direction must be set. You can configure a GPIO pin as either input (to read data) or output (to control devices).

To set the GPIO pin as an input:

int gpio_direction_input(unsigned int gpio);

To set the GPIO pin as an output:

int gpio_direction_output(unsigned int gpio, int value);
  • value: The initial output value (0 for low, 1 for high).

Example:

gpio_direction_output(17, 1);  // Set GPIO 17 as output, initial value HIGH
gpio_direction_input(18);      // Set GPIO 18 as input

3. gpio_set_value() and gpio_get_value()

Once the GPIO pin has been configured, you can use these functions to either set an output value or read an input value.

To set the output value:

void gpio_set_value(unsigned int gpio, int value);
  • value: 0 (low) or 1 (high).

Example:

gpio_set_value(17, 0);  // Set GPIO 17 to LOW

To get the input value:

int gpio_get_value(unsigned int gpio);

Example:

int value = gpio_get_value(18);  // Read the value from GPIO 18

4. gpio_free()

Once you are done using the GPIO pin, it should be freed to make it available for other parts of the system.

void gpio_free(unsigned int gpio);

Example:

gpio_free(17);  // Free GPIO 17

Step-by-Step Example: Controlling an LED with a Kernel Driver

Let’s walk through a simple example of controlling an LED using the GPIO API in a kernel driver.

  1. GPIO Pin: Assume the LED is connected to GPIO pin 17.
  2. Objective: We will write a kernel driver that turns the LED on and off.

Example Code:

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/init.h>

#define LED_GPIO 17  // GPIO pin where LED is connected

static int __init led_init(void)
{
    int ret;

    // Request the GPIO pin for LED
    ret = gpio_request(LED_GPIO, "led_gpio");
    if (ret) {
        printk(KERN_ERR "Unable to request GPIO pin %d\n", LED_GPIO);
        return ret;
    }

    // Set GPIO direction to output and turn the LED ON (HIGH)
    gpio_direction_output(LED_GPIO, 1);
    printk(KERN_INFO "LED turned ON\n");

    return 0;
}

static void __exit led_exit(void)
{
    // Turn the LED OFF (LOW) before exiting
    gpio_set_value(LED_GPIO, 0);
    printk(KERN_INFO "LED turned OFF\n");

    // Free the GPIO pin
    gpio_free(LED_GPIO);
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple LED control using GPIO in Linux kernel");

Explanation:

  • gpio_request(LED_GPIO, “led_gpio”): Requests the GPIO pin 17 and reserves it for the LED.
  • gpio_direction_output(LED_GPIO, 1): Sets GPIO 17 as an output pin and turns the LED on (sets the pin to high).
  • gpio_set_value(LED_GPIO, 0): Turns the LED off before the module is removed.
  • gpio_free(LED_GPIO): Frees the GPIO pin when the driver is unloaded.

Handling GPIO Interrupts

GPIO pins can also trigger interrupts. For example, a button press could generate an interrupt that signals the CPU to handle the event immediately.

To handle interrupts in a Linux kernel driver, you use the request_irq() function, along with an IRQ number associated with the GPIO pin. Here’s a basic example:

int irq = gpio_to_irq(GPIO_PIN);  // Get IRQ number for GPIO_PIN
request_irq(irq, gpio_interrupt_handler, IRQF_TRIGGER_RISING, "gpio_irq", NULL);

In this example:

  • gpio_to_irq() converts the GPIO pin number into the corresponding IRQ number.
  • request_irq() registers the interrupt handler (gpio_interrupt_handler) for the GPIO pin.

The Linux kernel GPIO API provides a simple yet powerful way to control GPIO pins in a platform-agnostic manner. Whether you’re writing drivers for embedded systems or controlling hardware peripherals, mastering these APIs will give you the flexibility to interface with a wide variety of hardware devices.

By following the steps and examples outlined in this guide, you can confidently start working with GPIOs in your Linux kernel projects.

Leave a Comment