Mastering Linux GPIO: Driver APIs, Sysfs, and PinCtrl Integration
This guide explains Linux GPIO fundamentals, driver APIs for requesting, configuring, and reading/writing pins, and demonstrates how to use the pinctrl subsystem with device‑tree examples for both single GPIOs and GPIO arrays.
Introduction
This article targets developers working with Linux kernel GPIO on versions 3.13 and later. It covers basic GPIO concepts, sysfs and debug interfaces, and introduces the pinctrl subsystem for more advanced pin configuration.
GPIO Subsystem API Overview
Key Functions
int gpio_request(unsigned gpio, const char *label)– request a GPIO line; returns 0 on success.
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)– request a GPIO with direction flags. void gpio_free(unsigned gpio) – release a previously requested GPIO. int gpio_direction_input(unsigned gpio) – set GPIO as input. int gpio_direction_output(unsigned gpio, int value) – set GPIO as output with an initial value. void __gpio_set_value(unsigned gpio, int value) (macro gpio_set_value) – write a value. int __gpio_get_value(unsigned gpio) (macro gpio_get_value) – read a value. int gpio_to_irq(unsigned gpio) – map a GPIO to an IRQ number.
Parameter Details
Each function’s parameters are documented, e.g., gpio is the numeric identifier, label is a descriptive name, and return values are 0 for success or a negative error code.
Example: Controlling a Single GPIO
Device‑tree snippet to request gpio4 as an output set high:
gpio_test{
status="ok";
gpio_req=<&tlmn 4 0>;
}Driver code:
struct device dev;
int gpio4 = of_get_named_gpio(dev.of_node, "gpio_req", 0);
int err = gpio_request(gpio4, "qti-can-reset");
if (err < 0) return err;
gpio_direction_output(gpio4, 0);
gpio_set_value(gpio4, 1);For a GPIO array, the device‑tree can list multiple pins and associated labels, e.g.,
gpios = <&tlmm 36 0>, <&tlmm 42 0>, <&tlmm 132 0>;with corresponding qcom,gpio-reset, qcom,gpio-standby, etc.
PinCtrl Subsystem Integration
Relevant APIs
struct pinctrl *devm_pinctrl_get(struct device *dev)– obtain pinctrl handle from device tree.
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)– retrieve a named pin configuration state.
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)– apply the selected state to hardware.
Example: Qualcomm Pin Configuration
&tlmn{
pin_test_default:pin_test_default{
mux {
pins = "gpio0", "gpio1";
function = "qup00";
};
config {
pins = "gpio0", "gpio1";
drive-strength = <2>;
bias-disable;
};
};
}Device‑tree entry to use the state:
pinctrl_test{
status="ok";
pinctrl-name="default";
pinctrl-0=<&pin_test_default>;
}Driver code to bind and select the state:
dev->pins->p = devm_pinctrl_get(dev);
dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_DEFAULT);
pinctrl_select_state(dev->pins->p, dev->pins->default_state);During the probe phase, the kernel automatically binds pinctrl resources, so the driver can rely on the pre‑initialized states without extra manual configuration.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
