为何gpiod_get_array()无法获取gpiod_count()识别到的GPIO描述符?
问题分析与解决方案
核心问题:GPIO属性放错了节点
你把my-gpios和my-gpio-names放在了&am33xx_pinmux(pinmux控制器节点)里,但gpiod_get系列函数是给功能设备节点用的,pinmux节点本身没资格请求GPIO。pinmux的职责只是配置引脚复用模式(比如把引脚设成GPIO功能),不是直接用GPIO的。
为啥gpiod_count能拿到数,但拿不到描述符?
gpiod_count只是单纯解析设备树属性里的GPIO数量,不做合法性校验,所以哪怕属性放错节点,它也能统计出个数。devm_gpiod_get_array/devm_gpiod_get_index会做严格校验:检查节点是不是合法的GPIO使用者,pinmux节点不属于这类,直接返回错误。
修复步骤
1. 调整设备树结构
把my-gpios和my-gpio-names移到实际要用GPIO的功能设备节点里,同时在pinmux节点里加对应的引脚复用配置,确保这些引脚被设为GPIO功能:
&am33xx_pinmux { pinctrl-names = "default"; // 配置引脚为GPIO功能的pinmux条目(偏移地址根据AM335X引脚手册调整) my_gpio_pins: my-gpio-pins { pinctrl-single,pins = < 0x110 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_4 */ 0x114 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_3 */ 0x11C (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_0 */ >; }; }; // 自定义一个功能设备节点,用来挂载GPIO属性 my_gpio_device: my-gpio-device { compatible = "my,gpio-device"; pinctrl-names = "default"; pinctrl-0 = <&my_gpio_pins>; // 绑定pinmux配置 my-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>, <&gpio2 3 GPIO_ACTIVE_HIGH>, <&gpio2 0 GPIO_ACTIVE_HIGH>; my-gpio-names = "name1", "name2", "name3"; status = "okay"; };
2. 调整驱动代码
让你的驱动绑定到上面的my-gpio-device节点(或者你实际要控制GPIO的设备节点),再调用gpiod系列函数就能正常拿描述符了:
// 假设dev是my-gpio-device对应的device结构体 int gpio_count, gpio_name_count; struct gpio_descs *gpiodescs; struct gpio_desc *desc; int i; gpio_count = gpiod_count(dev, "my"); if (gpio_count <= 0) { dev_err(dev, "没找到GPIO\n"); return -ENODEV; } gpio_name_count = of_property_count_strings(dev->of_node, "my-gpio-names"); if (gpio_name_count != gpio_count) { dev_warn(dev, "GPIO数量和名称数量不匹配\n"); } gpiodescs = devm_gpiod_get_array(dev, "my", GPIOD_OUT_LOW); if (IS_ERR(gpiodescs)) { dev_err(dev, "获取GPIO数组失败:%ld\n", PTR_ERR(gpiodescs)); return PTR_ERR(gpiodescs); } // 导出每个GPIO并关联名称 for (i = 0; i < gpiodescs->ndescs; i++) { char name[32]; desc = gpiodescs->desc[i]; if (gpiod_export(desc, false) < 0) { dev_warn(dev, "导出GPIO %d失败\n", i); continue; } if (of_property_read_string_index(dev->of_node, "my-gpio-names", i, name) == 0) { if (gpiod_export_link(dev, name, desc) < 0) { dev_warn(dev, "为GPIO %d创建名称链接失败\n", i); } } }
额外说明
- 导出后用
gpioinfo就能看到这些GPIO标记为used,因为gpiod_get系列函数会把GPIO标记为内核驱动正在使用。 - 要确保驱动和目标设备节点正确绑定,通过
compatible属性匹配或者平台设备注册的方式都行。
内容的提问来源于stack exchange,提问作者Glen G
相关产品推荐
相关产品推荐

