openbmc大多数设备的dts中,gpio的名字都在gpio-line-names中命名
如aspeed-bmc-opp-romulus.dts中
&gpio {
gpio-line-names =
/*A0-A7*/ "","cfam-reset","","","","","fsi-mux","",
/*B0-B7*/ "","","","","","","","",
/*C0-C7*/ "","","","","","","","",
/*D0-D7*/ "fsi-enable","","","nic_func_mode0","nic_func_mode1","","","",
/*E0-E7*/ "","","","","","","","",
/*F0-F7*/ "","","","","","","","",
/*G0-G7*/ "","","","","","","","",
/*H0-H7*/ "","","","","","","","",
/*I0-I7*/ "","","","power-button","","","","",
/*J0-J7*/ "","","checkstop","","","","","",
/*K0-K7*/ "","","","","","","","",
/*L0-L7*/ "","","","","","","","",
/*M0-M7*/ "","","","","","","","",
/*N0-N7*/ "","","led-fault","",
"led-identify","","","",
/*O0-O7*/ "","","","","","","","",
/*P0-P7*/ "","","","","","","","",
/*Q0-Q7*/ "","","","","","","","id-button",
/*R0-R7*/ "","","fsi-trans","","","led-power","","",
/*S0-S7*/ "","","","","","","","seq_cont",
/*T0-T7*/ "","","","","","","","",
/*U0-U7*/ "","","","","","","","",
/*V0-V7*/ "","","","","","","","",
/*W0-W7*/ "","","","","","","","",
/*X0-X7*/ "","","","","","","","",
/*Y0-Y7*/ "","","","","","","","",
/*Z0-Z7*/ "","","","","","","","",
/*AA0-AA7*/ "fsi-clock","","fsi-data","","","","","",
/*AB0-AB7*/ "","","","","","","","",
/*AC0-AC7*/ "","","","","","","","";
...
};
而aspeed-bmc-lenovo-hr630.dts中,出现了在subnode中用line-name这个property命名的方式
&gpio {
pin_gpio_a1 {
gpio-hog;
gpios = <ASPEED_GPIO(A, 1) GPIO_ACTIVE_LOW>;
output-high;
line-name = "BMC_EMMC_RST_N";
};
...
};
两种命名方式有何区别呢?
以下是代码层面创建gpio设备的代码调用栈:
aspeed_gpio_probe
gpiochip_add_data
devm_gpiochip_add_data_with_key
gpiochip_add_data_with_key
of_gpiochip_add
devprop_gpiochip_set_names
fwnode_property_read_string_array(fwnode, "gpio-line-names", NULL, 0)
gdev->descs[i].name =
of_gpiochip_scan_gpios
of_gpiochip_add_hog
of_parse_own_gpio
of_property_read_string(np, "line-name", name)
gpiod_hog
gpiochip_request_own_desc
gpiod_request_commit
desc_set_label
gdev->descs[i].label =
可见属性gpio-line-names最终赋值给了desc的name变量
而line-name最终赋值给了desc的label变量
那最终应用有何区别呢?
应用中对于gpio的操作基本是基于libgpiod这个库
阅读库源码可以得知驱动中的name变量在libgpiod的gpio信息结构中仍然叫做name,而驱动中的label在libgpiod中被命名为consumer
对于拥有gpio-hog属性的gpio,在libgpiod读取gpio信息时,内核会标记其flag为GPIOLINE_FLAG_KERNEL
在调用gpioinfo的时候,会显示label,否则显示为unused
后续用gpioset等其他操作时,底层会再次调用gpiod_request_commit
如果gpio被配置为gpio-hog,由于内核之前已经执行过gpiod_request_commit了,那么应用中再次请求就会失败,返回EBUSY
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
{
……
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
desc_set_label(desc, label ? : "?");
ret = 0;
} else {
kfree_const(label);
ret = -EBUSY;
goto done;
}
……
}
由此可见gpio驱动中的label属性,实际就是用来标记当前gpio的拥有者是谁
总上所述,gpio-line-names和line-name虽然都包含name,但是其用途是不一样的
gpio-line-names是真正用来表示名字的
而line-name是用于记录gpio的控制者
如果希望gpio在应用层能够控制,就不能配置gpio-hog属性,而没有gpio-hog属性的话,line-name也就没有意义了
看来gpio-hog是为了安全性而提供的一种机制,将需要动态配置的gpio在内核态写死
完