Published on

How to Write a Raspberry Pi GPIO Driver: Ultimate Guide for Pi 3/4/5 (2025)

Authors

How to Write a Raspberry Pi GPIO Driver


Introduction

As a Linux kernel developer consultant with over 20 years of experience in Android Board Support Package (BSP) development for several OEM smartphone companies like Samsung, Motorola, LG, and Sony Ericsson, I've tackled complex driver challenges, including authoring the CAIF network driver for ST-Ericsson's ARM platforms pushed to upstream Linux Kernel source. General Purpose Input/Output (GPIO) drivers are critical for controlling hardware like LEDs, sensors, and buttons on Raspberry Pi, a staple in embedded systems and IoT projects. Whether you're building a smart home device or debugging a kernel module, mastering GPIO drivers is essential.

This guide provides a comprehensive, step-by-step tutorial on writing a Raspberry Pi GPIO driver for Pi 3, 4, and 5, with a focus on the Pi 5's RP1 chip. Unlike outdated tutorials stuck on older Pi models or fragmented forum posts, this article covers modern Raspberry Pi OS (2025), kernel 6.6, and advanced debugging techniques. You'll get working code, a device tree overlay, and a free GPIO debug script. Let's dive in!

Explore my OV5647 camera driver guide for more embedded insights or try my ICCID Validator for IoT projects.


What is a Raspberry Pi GPIO Driver?

GPIO drivers allow software to interact with Raspberry Pi's general-purpose pins, enabling control of external devices like LEDs or sensors. As someone who's written network drivers like CAIF for ARM platforms, I can attest that GPIO drivers share similar principles: precise register manipulation and kernel integration. Here's a quick overview:

  • GPIO Purpose: GPIO pins handle input (e.g., button presses) or output (e.g., LED toggling). Drivers run in kernel space for performance, unlike user-space tools like sysfs.

  • Raspberry Pi Models:

    • Pi 3/4: Use BCM2711 SoC with direct GPIO access via registers.
    • Pi 5: Introduces the RP1 chip, a southbridge managing GPIO over a PCI bus, requiring updated driver techniques.
  • APIs: Modern kernels use the gpiod library (gpiod_set_value, gpio_request_one) for robust GPIO control, replacing older gpio APIs.

Model GPIO Pins Access Methods Kernel API
Pi 3 26 BCM2711 (direct) gpiod/sysfs
Pi 4 26 BCM2711 (direct) gpiod/sysfs
Pi 5 26 RP1 (PCI bus) gpiod/pinctrl
Raspberry Pi GPIO Driver Pinout

This guide builds a driver for all models, with Pi 5-specific tweaks to address the RP1 chip, a gap in many tutorials.

Need a Raspberry Pi 5 to start? Grab one here.


Setting Up Your Raspberry Pi GPIO Driver Environment

To write a GPIO driver, you need a proper development environment. Many guides, like those from 2018, reference outdated tools or Pi 3 setups. This section uses Raspberry Pi OS (Bookworm, 2025) and kernel 6.6, compatible with Pi 3, 4, and 5.

Prerequisites

  • Hardware: Raspberry Pi 3/4/5, LED, 220Ω resistor, breadboard, jumper wires.
  • Software: Raspberry Pi OS (Bookworm, 2025), GCC 12.x, kernel headers.
  • Setup Steps:
    1. Install Dependencies
      sudo apt update
      sudo apt install build-essential raspberrypi-kernel-headers git
      
    2. Clone Kernel Source:
      git clone --depth=1 -b rpi-6.6.y https://github.com/raspberrypi/linux
      
    3. Set Cross-Compiler (Pi 5, ARM64):
      export CROSS_COMPILE=aarch64-linux-gnu-
      export ARCH=arm64
      
    4. Configure Kernel
      make bcm2711_defconfig
      
  • Pi 5 Note: The RP1 chip requires PCI bus awareness for GPIO access, unlike BCM2711’s direct mapping. We'll cover this in the device tree section.

Get a breadboard kit for testing here.


Writing a Raspberry Pi GPIO Driver: Step-by-Step Code

Let us write a kernel module to control an LED on GPIO 21, compatible with Pi 3/4/5. This driver uses the modern gpiod API, improving on older gpio methods in older tutorials found on the internet.

Driver Code

Below is a complete C driver to toggle an LED on GPIO 21, with error handling for robustness.

#include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>

static struct gpio_desc *led_gpio;

static int __init gpio_driver_init(void) {
    int ret;
    led_gpio = gpiod_get(NULL, "gpio21", GPIOD_OUT_LOW);
    if (IS_ERR(led_gpio)) {
        printk(KERN_ERR "GPIO request failed: %ld\n", PTR_ERR(led_gpio));
        return PTR_ERR(led_gpio);
    }
    gpiod_set_value(led_gpio, 1); // Turn LED on
    printk(KERN_INFO "GPIO Driver Loaded for Raspberry Pi\n");
    return 0;
}

static void __exit gpio_driver_exit(void) {
    gpiod_set_value(led_gpio, 0); // Turn LED off
    gpiod_put(led_gpio);
    printk(KERN_INFO "GPIO Driver Unloaded\n");
}

module_init(gpio_driver_init);
module_exit(gpio_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Amarnath B R <digitallyamar@gmail.com>");
MODULE_DESCRIPTION("Raspberry Pi GPIO Driver for LED Control");

Explanation

  • API Choice: Uses gpiod_get for modern GPIO handling, avoiding deprecated gpio_request (seen in older tutorials).
  • Error Handling: Checks for EBUSY or EINVAL errors, critical for Pi 5’s RP1 chip.

Device Tree Overlay (Pi 5)

For Pi 5, configure the RP1 chip's GPIO via a device tree overlay:

/dts-v1/;
/plugin/;
/ {
    compatible = "brcm,bcm2712";
    fragment@0 {
        target = <&gpio>;
        __overlay__ {
            led_gpio: led_gpio {
                brcm,pins = <21>;
                brcm,function = <1>; // Output
                brcm,pull = <2>; // Pull-up
            };
        };
    };
};
  • Save: As led-gpio.dts.
  • Compile: dtc -@ -I dts -O dtb -o led-gpio.dtbo led-gpio.dts.
  • Apply: Copy to /boot/overlays/ and add dtoverlay=led-gpio to /boot/config.txt.

Compilation and Loading

1. Compile:

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

2. Load:

sudo insmod gpio_driver.ko

3. Verify: Check dmesg for "GPIO Driver Loaded."


Debugging Your Raspberry Pi GPIO Driver

Debugging is critical, as errors like EBUSY or kernel panics are common. Unlike fragmented forum posts or other blog's basic dmesg tips, this section offers advanced techniques.

Common Issues and Fixes

Error Cause Fix
EBUSY GPIO in use Check /sys/kernel/debug/gpio, free via echo 21 > /sys/class/gpio/unexport
EINVAL Invalid pin Verify RP1 pin mapping for Pi 5 (GPIO 0-27)
Kernel Panic Bad register access Use device tree overlay, disable /dev/mem direct access

Debugging Steps

  1. Check GPIO Status:
    cat /sys/kernel/debug/gpio
    
    Output example: gpiochip4: GPIOs 0-27, parent: platform/soc, gpio: GPIO 21 (led_gpio | output | active).
  2. Monitor Logs:
    sudo dmesg | grep GPIO
    
  3. Test via Sysfs (Fallback):
    echo 21 > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio21/direction
    echo 1 > /sys/class/gpio/gpio21/value
    
  4. Advanced: Use gdb for kernel debugging or pinctrl for Pi 5:
    pinctrl set 21 op pu
    

My CAIF driver work on ST-Ericsson ARM platforms taught me to prioritize dmesg parsing for driver issues, a technique that applies here.

Need expert BSP debugging? Contact me for consulting (digitallyamar@gmail.com) ($50-100/hour)


GPIO Drivers on Raspberry Pi 5: Handling the RP1 Chip

The Raspberry Pi 5's RP1 chip, a southbridge managing GPIO via PCI, introduces unique challenges absent in Pi 3/4 (BCM2711 direct access). Many tutorials ignore this.

  • RP1 Overview: Handles GPIO, I2C, and UART via PCI bus, requiring updated device tree and pinctrl configurations.
  • Challenges:
    • Pin mapping differs (e.g., GPIO 21 on RP1 vs. BCM2711).
    • PCI driver integration needed for kernel modules.
  • Solutions:
    • Use device tree overlay (above) to map GPIO 21.
    • Verify pin functions: pinctrl get 21 (output, pull-up).
    • Update kernel config: Enable CONFIG_PINCTRL_RP1=y.

This ensures compatibility, unlike outdated guides stuck on older models.

Get a Raspberry Pi 5 here to experiment with RP1.


Frequently Asked Questions About Raspberry Pi GPIO Drivers

Q1: Why does gpio_request fail on Raspberry Pi 5? A: Common causes include EBUSY (GPIO in use) or incorrect RP1 pin mapping. Check /sys/kernel/debug/gpio and free pins via sysfs.

Q2: How to toggle GPIO pins without a kernel driver? A: Use sysfs: echo 21 > /sys/class/gpio/export; echo out > /sys/class/gpio/gpio21/direction; echo 1 > /sys/class/gpio/gpio21/value.

Q3: What’s the difference between sysfs and gpiod APIs? A: Sysfs (/sys/class/gpio) is user-space, slower, and simpler; gpiod is kernel-space, faster, and supports advanced features like interrupts.


Conclusion

This guide equips you to write a Raspberry Pi GPIO driver for Pi 3, 4, and 5, with modern kernel 6.6 code, Pi 5 RP1 chip support, and advanced debugging tips. Unlike fragmented forum posts or outdated tutorials, it consolidates 20+ years of my BSP expertise, including my CAIF driver work, into a practical tutorial.

Resources:

Share your GPIO challenges in the comments below!


OV5647 driver Video capture demo

A typical Linux kernel driver compilation demo video.