设备树中gpio属性gpio-line-names和line-name的区别

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在内核态写死

上一篇:用好idea,让你更方便的程序错误/漏洞跟踪调试


下一篇:linux arm irq (2): interrupt handling