内核模块中使用GPIO描述符接口遇问题,求技术指引
gpiod_get() Returning ffffffff in Your Kernel Driver Hey there! Let's dig into why your gpiod_get() call is returning that ffffffff value—for context, that's a negative error code represented in unsigned hex (like -19 for EPROBE_DEFER shows up as 0xffffffed). Here's a step-by-step breakdown of common issues and fixes:
First, validate your device tree (or ACPI) GPIO bindings
The descriptor-based GPIO interface relies on your device having the correct GPIO property defined. For example, if your power-enable GPIO is connected to line 10 ongpiochip0, your device tree node should include:my_device { compatible = "vendor,my-device"; power-gpios = <&gpiochip0 10 GPIO_ACTIVE_HIGH>; };Make sure:
- The GPIO number matches the actual line on your GPIO controller.
- The active level (
GPIO_ACTIVE_HIGH/GPIO_ACTIVE_LOW) matches your hardware's requirement. - If you're not using device tree, you'll need to set up explicit GPIO mappings (but device tree is the modern, recommended approach).
Double-check your
gpiod_get()parameters
The function signature isstruct gpio_desc *gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags);dev: Ensure this is a valid pointer to your device'sstruct device(in probe functions, this is the parameter passed to you—don't pass NULL!).con_id: This must match the suffix of your device tree property. For example, if your property ispower-gpios, use"power"as thecon_id(the framework automatically appends-gpiosto look up the property).flags: UseGPIOD_OUT_HIGHif you want to set the GPIO high immediately,GPIOD_OUT_LOWto start low, orGPIOD_ASISif you need to set the direction later withgpiod_direction_output().
Handle
EPROBE_DEFERcorrectly
Thatffffffffvalue might beEPROBE_DEFER, which means the GPIO controller driver hasn't loaded yet. You need to defer your probe so the kernel tries again later:struct gpio_desc *power_gpio; power_gpio = gpiod_get(dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(power_gpio)) { int err = PTR_ERR(power_gpio); if (err == -EPROBE_DEFER) return err; dev_err(dev, "Failed to get power GPIO: %d\n", err); return err; }Always use
IS_ERR()to check the return value, andPTR_ERR()to get the actual error code—don't just rely on the hex value!Check if the GPIO line is already in use
Another common issue is the GPIO line being claimed by another driver. You can verify this with:cat /sys/kernel/debug/gpioLook for your GPIO line—if it's marked as "used" by another device/driver, you'll need to free it up or adjust your device tree.
Use devres functions for safer resource management
To avoid resource leaks, usedevm_gpiod_get()instead ofgpiod_get(). It automatically cleans up the GPIO descriptor when your device is removed, so you don't have to callgpiod_put()manually:struct gpio_desc *power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(power_gpio)) { int err = PTR_ERR(power_gpio); if (err == -EPROBE_DEFER) return err; dev_err(dev, "Failed to get power GPIO: %d\n", err); return err; }Quick debug tip: Print the actual error code
Add a debug print to see exactly what's going wrong:struct gpio_desc *gpiod = gpiod_get(dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(gpiod)) { dev_err(dev, "gpiod_get failed with error: %d\n", PTR_ERR(gpiod)); return PTR_ERR(gpiod); }This will tell you if it's
ENOENT(GPIO property missing),EBUSY(line in use), orEPROBE_DEFER(need to wait for the GPIO controller).
内容的提问来源于stack exchange,提问作者guenni_90

