GPIO 對映¶
本文件解釋瞭如何將 GPIO 分配給給定的裝置和功能。
所有平臺都可以啟用 GPIO 庫,但如果平臺嚴格要求存在 GPIO 功能,則需要從其 Kconfig 中選擇 GPIOLIB。然後,GPIO 的對映方式取決於平臺使用什麼來描述其硬體佈局。目前,可以透過裝置樹、ACPI 和平臺數據來定義對映。
裝置樹¶
在裝置樹中,GPIO 可以很容易地對映到裝置和功能。確切的做法取決於提供 GPIO 的 GPIO 控制器,請參閱控制器的裝置樹繫結。
GPIO 對映在消費者裝置的節點中定義,位於名為 <function>-gpios 的屬性中,其中 <function> 是驅動程式將透過 gpiod_get() 請求的功能。例如
foo_device {
compatible = "acme,foo";
...
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};
名為 <function>-gpio 的屬性也被認為是有效的,舊的繫結使用它,但僅出於相容性原因才支援它,不應將其用於較新的繫結,因為它已被棄用。
此屬性將使 GPIO 15、16 和 17 在驅動程式中以“led”功能提供,並將 GPIO 1 作為“power” GPIO 提供
struct gpio_desc *red, *green, *blue, *power;
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);
led GPIO 將是高電平有效,而 power GPIO 將是低電平有效(即 gpiod_is_active_low(power) 將為真)。
gpiod_get() 函式的第二個引數,con_id 字串,必須是裝置樹中使用的 GPIO 字尾(“gpios”或“gpio”,由 gpiod 函式在內部自動查詢)的 <function>- 字首。 對於上面的 “led-gpios” 示例,請使用不帶 “-” 的字首作為 con_id 引數:“led”。
在內部,GPIO 子系統將 GPIO 字尾(“gpios”或“gpio”)與 con_id 中傳遞的字串作為字首,以獲得結果字串 (snprintf(... "%s-%s", con_id, gpio_suffixes[])。
ACPI¶
ACPI 還支援 GPIO 的功能名稱,方式與 DT 類似。 上面的 DT 示例可以在 ACPI 5.1 中引入的 _DSD(裝置特定資料)的幫助下轉換為等效的 ACPI 描述
Device (FOO) {
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 15 } // red
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 16 } // green
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 17 } // blue
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 1 } // power
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {
"led-gpios",
Package () {
^FOO, 0, 0, 1,
^FOO, 1, 0, 1,
^FOO, 2, 0, 1,
}
},
Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } },
}
})
}
有關 ACPI GPIO 繫結的更多資訊,請參閱 與 GPIO 相關的 _DSD 裝置屬性。
平臺數據¶
最後,可以使用平臺數據將 GPIO 繫結到裝置和功能。 希望這樣做的板檔案需要包含以下標頭檔案
#include <linux/gpio/machine.h>
GPIO 透過查詢表進行對映,查詢表包含 gpiod_lookup 結構的例項。 定義了兩個宏來幫助宣告此類對映
GPIO_LOOKUP(key, chip_hwnum, con_id, flags)
GPIO_LOOKUP_IDX(key, chip_hwnum, con_id, idx, flags)
其中
key 是提供 GPIO 的 gpiod_chip 例項的標籤,或者是 GPIO 線路名稱
chip_hwnum 是晶片中 GPIO 的硬體編號,如果 key 是 GPIO 線路名稱,則為 U16_MAX
- con_id 是從裝置角度來看的 GPIO 功能的名稱。 它
可以為 NULL,在這種情況下,它將匹配任何功能。
idx 是功能中 GPIO 的索引。
- 定義 flags 以指定以下屬性
GPIO_ACTIVE_HIGH - GPIO 線路為高電平有效
GPIO_ACTIVE_LOW - GPIO 線路為低電平有效
GPIO_OPEN_DRAIN - GPIO 線路設定為開漏
GPIO_OPEN_SOURCE - GPIO 線路設定為開源
- GPIO_PERSISTENT - GPIO 線路在
掛起/恢復期間保持不變並保持其值
- GPIO_TRANSITORY - GPIO 線路是短暫的,並且可能失去其
在掛起/恢復期間的電氣狀態
將來,這些標誌可能會擴充套件以支援更多屬性。
- 請注意
GPIO 線路名稱不能保證是全域性唯一的,因此將使用找到的第一個匹配項。
GPIO_LOOKUP() 只是 GPIO_LOOKUP_IDX() 的快捷方式,其中 idx = 0。
然後可以按如下方式定義查詢表,其中一個空條目定義了其結尾。 該表的“dev_id”欄位是使用這些 GPIO 的裝置的識別符號。 它可以為 NULL,在這種情況下,它將與對 gpiod_get() 的呼叫匹配,其中裝置為 NULL。
struct gpiod_lookup_table gpios_table = {
.dev_id = "foo.0",
.table = {
GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW),
{ },
},
};
並且可以按如下方式將表新增到板程式碼中
gpiod_add_lookup_table(&gpios_table);
然後,控制“foo.0”的驅動程式可以按如下方式獲取其 GPIO
struct gpio_desc *red, *green, *blue, *power;
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);
由於“led”GPIO 對映為高電平有效,因此此示例會將它們的訊號切換為 1,即啟用 LED。 對於對映為低電平有效的“power”GPIO,此程式碼後的實際訊號將為 0。 與傳統的整數 GPIO 介面相反,低電平有效屬性在對映期間處理,因此對 GPIO 使用者是透明的。
諸如 gpiod_set_value() 之類的一組函式可用於使用新的面向描述符的介面。
使用平臺數據的板還可以透過定義 GPIO hog 表來佔用 GPIO 線路。
struct gpiod_hog gpio_hog_table[] = {
GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH),
{ }
};
並且可以按如下方式將表新增到板程式碼中
gpiod_add_hogs(gpio_hog_table);
一旦建立 gpiochip,或者 - 如果晶片是較早建立的 - 當註冊 hog 表時,該線路將被佔用。
引腳陣列¶
除了逐個請求屬於某個功能的引腳之外,裝置還可以請求分配給該功能的引腳陣列。 這些引腳對映到裝置的方式決定了該陣列是否符合快速點陣圖處理的條件。 如果符合條件,則點陣圖會在呼叫者和 GPIO 晶片的相應 .get/set_multiple() 回撥之間直接透過 get/set 陣列函式傳遞。
為了符合快速點陣圖處理的條件,該陣列必須滿足以下要求
陣列成員 0 的引腳硬體編號也必須為 0,
屬於與成員 0 相同的晶片的連續陣列成員的引腳硬體編號也必須與其陣列索引匹配。
否則,不使用快速點陣圖處理路徑,以避免屬於同一晶片但不按硬體順序排列的連續引腳被單獨處理。
如果該陣列適用於快速點陣圖處理路徑,則屬於與成員 0 不同的晶片的引腳,以及索引與硬體引腳編號不同的引腳,都將從快速路徑中排除,無論是輸入還是輸出。 此外,開漏和開源引腳將從快速點陣圖輸出處理中排除。