# 配置 pinctrl 驅動程式

Qualcomm Linux 核心中的 Pinctrl 子系統管理和配置用於通用輸入 / 輸出 (GPIO)、積體匯流排電路 (I2C)、序列周邊介面 (SPI) 及其他硬體介面的接腳。

在裝置專用的 pinctrl 驅動程式中管理 pinctrl 組態 (例如 **接腳多工** 和 **接腳分組**，驅動程式會列出所有可用的接腳和函式。

例如，`kernel-src/drivers/pinctrl/qcom/pinctrl-sc7280.c` 檔案中提供 QCS6490 的對應驅動程式。

備註

欲深入瞭解其他 Qualcomm SoC pinctrl 驅動程式，請參閱 [Pinctrl Drivers](https://github.com/torvalds/linux/tree/master/drivers/pinctrl/qcom)。

以下是 pinctrl 資料物件：

表：Pinctrl 資料物件

| 變數 | 說明 |
| --- | --- |
| static const struct pinctrl_pin_desc sc7280_pins<br>    Copy to clipboard | 列舉所有接腳及其名稱 |
| static const struct msm_pingroup sc7280_groups<br>    Copy to clipboard | 定義 GPIO 接腳群組可用的多工功能 |
| enum sc7280_functions<br>    Copy to clipboard | 將所有可用函式列為列舉值 |

欲深入瞭解各個 SoC pinctrl 繫結支援的函式，請參閱 [pinctrl binding documentation](https://www.kernel.org/doc/Documentation/devicetree/bindings/pinctrl/qcom%2Csc7280-pinctrl.yaml)。

**函式選擇**

針對 `sc7280_functions` 資料物件，使用一或多個 GPIO 接腳作為函式，必須登錄至裝置樹並傳遞給正確的裝置節點。

在系統啟動過程中，核心 pinctrl 基礎架構會登錄函式。

以下範例呈現核心組態基礎架構：

tlmm: pinctrl@f100000 {
        compatible = "qcom,sc7280-pinctrl";
        :
        :
        :
        :
        qup_spi0_data_clk: qup-spi0-data-clk-state {
            pins = "gpio0", "gpio1", "gpio2";
            function = "qup00";
        };
    
        qup_spi0_cs: qup-spi0-cs-state {
            pins = "gpio3";
            function = "qup00";
        };
    
        qup_spi1_data_clk: qup-spi1-data-clk-state {
            pins = "gpio4", "gpio5", "gpio6";
            function = "qup01";
        };
    
        qup_spi1_cs: qup-spi1-cs-state {
            pins = "gpio7";
            function = "qup01";
        };
        :
        :
        :
        :
    
    };

        spi0: spi@980000 {
            compatible = "qcom,geni-spi";
            reg = <0 0x00980000 0 0x4000>;
            clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
            clock-names = "se";
            pinctrl-names = "default";
            pinctrl-0 = <&qup_spi0_data_clk>, <&qup_spi0_cs>;
            interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
            #address-cells = <1>;
            #size-cells = <0>;
            power-domains = <&rpmhpd SC7280_CX>;
            operating-points-v2 = <&qup_opp_table>;
            interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
                    <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_QUP_0 0>;
            interconnect-names = "qup-core", "qup-config";
            dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
                <&gpi_dma0 1 0 QCOM_GPI_SPI>;
            dma-names = "tx", "rx";
            status = "disabled";
        };
    Copy to clipboard

## 配置 GPIO 用途

GPIO 接腳配置需要以下兩個設定。這些設定定義 GPIO 接腳狀態並使這些引腳可用於任何輸入/輸出活動。

- 多工：多工設定需要選擇從 SoC 專用 pinctrl 驅動程式的可用函式集中映射的函式名稱。

    欲深入瞭解 pinctrl，請參閱 [Pinctrl 組態](https://docs.qualcomm.com/doc/80-70020-3TC/topic/pinctrl-configuration.html#pinctrl-configuration)。
- 配置：配置層面需要設定驅動強度和偏差屬性。

以下範例說明這兩個設定如何依照下述程序定義 GPIO 接腳：

1. 在裝置樹中定義接腳配置：

bt_en: bt-en-state {
           pins = "gpio85";
           function = "gpio";
           output-low;
           bias-disable;
        };
        Copy to clipboard
2. 在裝置樹中配置裝置節點或智慧財產 (IP) 區塊：

bluetooth: bluetooth {
           compatible = "qcom,wcn6750-bt";
           pinctrl-names = "default";
           pinctrl-0 = <&bt_en>, <&sw_ctrl>;
           enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>;
           swctrl-gpios = <&tlmm 86 GPIO_ACTIVE_HIGH>;
           vddaon-supply = <&vreg_s7b_0p9>;
           vddbtcxmx-supply = <&vreg_s7b_0p9>;
           vddrfacmn-supply = <&vreg_s7b_0p9>;
           vddrfa0p8-supply = <&vreg_s7b_0p9>;
           vddrfa1p7-supply = <&vreg_s1b_1p8>;
           vddrfa1p2-supply = <&vreg_s8b_1p2>;
           vddrfa2p2-supply = <&vreg_s1c_2p2>;
           vddasd-supply = <&vreg_l11c_2p8>;
           max-speed = <3200000>;
        Copy to clipboard
3. 驅動程式程式碼必須使用通用 API 在 pinctrl 組態中選擇和登錄其 GPIO 配置。

    以下是可用 API 的範例：

> 
> 
> devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW);
>         
>         /**
>         * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
>         * @dev: GPIO consumer
>         * @con_id: function within the GPIO consumer
>         * @flags: optional GPIO initialization flags
>         *
>         * Managed gpiod_get_optional(). GPIO descriptors returned from this function
>         * are automatically disposed on driver detach. See gpiod_get_optional() for
>         * detailed information about behavior and return values. */
>         
>          gpiod_set_value_cansleep(qcadev->bt_en, 0);
>         
>         /**
>         * gpiod_set_value_cansleep() - assign a gpio's value
>         * @desc: gpio whose value will be assigned
>         * @value: value to assign
>         *
>         * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
>         * account
>         *
>         * This function is to be called from contexts that can sleep.
>         */
>         Copy to clipboard

**GPIO 作為中斷要求 (IRQ)**

若要將 GPIO 設為 IRQ，請依照下述程序操作：

1. 在 DTS 檔案中配置 GPIO 接腳：

    1. 設定 GPIO 接腳的屬性和函式。
    2. 設定接腳以將 GPIO 55 用於 `qup_se_l3()` 函式，組態如下：

qupv3_se3_rx: qupv3-se3-rx-state {
               pins = "gpio55";
               function = "qup03"; // To be taken from available from functions.
               drive-strength = <2>;
               bias-disable;
            };
            Copy to clipboard
2. 為要將 GPIO 設為 IRQ 的裝置節點建立與先前的組態相似的 DT 項目。

    在以下範例中，GPIO55 被配置為 IRQ，父系為頂層模式多工器 (TLMM)，層級設為高。

interrupts-extended = <&tlmm 55 IRQ_TYPE_LEVEL_HIGH>;
        Copy to clipboard
3. 驅動程式必須讀取該值，並使用 `request_irq` API 以中斷形式將它登錄至通用中斷控制器 (GIC)，指定中斷服務暫存器 (ISR) 和 IRQ 旗標。

irq_no = platform_get_irq(pdev, 1);
        Copy to clipboard

## 配置 GPIO 以產生時脈或脈衝寬度調變

為任何 GPIO 配置 `GP_CLK` 作為替代功能，以取得時脈或脈衝寬度調變 (PWM)。

備註

以下程序適用於 QCS6490 SoC。

欲深入瞭解如何使用 `GP_CLK` 函式尋找 GPIO，請參閱 [接腳描述](https://docs.qualcomm.com/bundle/publicresource/topics/80-23889-1/pin-definitions.html#sub$pin-descriptions:~:text=and%20available%20configurations.-,Table%20%3A%20Pin%20descriptions%20%E2%80%93%20general%2Dpurpose%20input/output%20ports,-Pad%20number)。

1. 在 `kernel/arch/arm64/boot/dts/qcom/sc7280.dtsi` 檔案中新增 GPIO 組態節點。

> 
> 
> +gpio_pwm_default: gpio_pwm_default {
>     +       mux {
>     +               pins = "gpio42";
>     +               function = "gcc_gp1";    // search "gcc_gp" in "kernel/drivers/pinctrl/qcom/pinctrl-sc7280.c", From this we can find out which GPIO's has GP_CLK functionality
>     +       };
>     +
>     +       config {
>     +               pins = "gpio42";
>     +               bias-disable; /* No PULL */
>     +               drive-strength = <8>; /* 2 MA */
>     +       };
>     +};
>     Copy to clipboard

2. 在 `kernel/arch/arm64/boot/dts/qcom/sc7280.dtsi` 檔案中定義裝置樹節點。

+beeper: beeper {
        +       compatible = "gpio-beeper";
        +       pinctrl-names = "default";
        +       pinctrl-0 = <&gpio_pwm_default>;
        +       clocks = <&clock_gcc GCC_GP1_CLK>; //clock_gcc is gcc clk device node, GCC_GP1_CLK index which defined in "kernel/include/dt-bindings/clock/qcom,gcc-sc7280.h"
        +       clock-names = "gpio-pwm-clk";
        +};
        Copy to clipboard
3. 在裝置驅動程式中新增以下程式碼：

+#include <linux/clk.h>
        +#include <linux/io.h>
        ...
        + struct clk *pclk;
        + struct rcg_clk *gp1_rcg_clk;
        + int ret;
        +
        + pclk = devm_clk_get(&pdev->dev, "gpio-pwm-clk");
        + ret = clk_set_rate(pclk, 50000000); // please check the freq table in kernel/drivers/clk/qcom/gcc-sc7280.c, the freq can be found in the freq table of GCC_GP1_CLK.
        + if (ret)
        +     printk("clk set rate fail, ret = %d\n", ret);
        +
        + ret = clk_prepare_enable(pclk);  // By default this will enable clock as PWM with 50% duty cycle.
        + if (ret)
        +     printk("%s: clk_prepare error!!!\n", __func__);
        + else
        +     printk("%s: clk_prepare success!\n", __func__);
        +
        Copy to clipboard
4. 如果不使用時脈或 PWM，請呼叫 `clk_disable_unprepare()` 停用時脈以便省電。

備註

請務必先呼叫 `clk_prepare_enable()`，再呼叫 `clk_disable_unprepare()`。
5. 若要產生所需的工作週期，請在 `clk_prepare_enable` API 之後呼叫 `clk_set_duty_cycle()` API。

## 從使用者空間配置 GPIO

從使用者空間使用 `libgpiod` 函式庫控制 GPIO，以獲得更好的效能。

1. 若要從主機電腦編譯並推送 `libgpiod` 函式庫，請執行以下操作：

    1. 若要安裝 Arm^®^ (Arm64) 工具鏈，請執行以下命令：

sudo apt install gcc-aarch64-linux-gnu
            Copy to clipboard

sudo apt install binutils-aarch64-linux-gnu
            Copy to clipboard
    2. 若要從 [libgpiod 1.6.4.tar.xz](https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-1.6.4.tar.xz) 下載並擷取 libgpiod 原始碼，請執行以下命令：

wget https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-1.6.4.tar.xz
            Copy to clipboard

tar xvf libgpiod-1.6.4.tar.xz
            Copy to clipboard

cd libgpiod-1.6.4
            Copy to clipboard
    3. 若要配置靜態連結的原始碼，請執行以下命令：

./configure --enable-tools=yes --build x86_64-pc-linux-gnu --host aarch64-linux-gnu CFLAGS="-static -static-libgcc -Wl,-static,--start-group,/usr/lib/gcc-cross/aarch64-linux-gnu/7.5.0/libgcc.a,/usr/lib/gcc-cross/aarch64-linux-gnu/7.5.0/libgcc_eh.a,/usr/aarch64-linux-gnu/lib/libc.a,--end-group"
            Copy to clipboard
    4. 若要編譯函式庫，請執行下列命令：

make
            Copy to clipboard

備註

編譯會建立連結的二進位檔案。
    5. 若要建置靜態連結的二進位檔案，請執行以下命令：

aarch64-linux-gnu-gcc -static -o tools/gpiodetect tools/gpiodetect.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard

aarch64-linux-gnu-gcc -static -o tools/gpioget tools/gpioget.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard

aarch64-linux-gnu-gcc -static -o tools/gpioset tools/gpioset.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard

aarch64-linux-gnu-gcc -static -o tools/gpiofind tools/gpiofind.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard

aarch64-linux-gnu-gcc -static -o tools/gpioinfo tools/gpioinfo.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard

aarch64-linux-gnu-gcc -static -o tools/gpiomon tools/gpiomon.o tools/tools-common.o -Wl,-L<ABSOLUTE_PATH_TO_LIBGPIOD>/libgpiod-1.6.4/lib/.libs,-lgpiod,-lpthread,-static
            Copy to clipboard
2. 若要在編譯後將二進位檔案推送至裝置，請執行 `scp` 命令。比如：

scp gpioinfo root@<IP_address>:/path/to/directory/on/device
        Copy to clipboard

將二進位檔案推送至裝置後，在裝置上執行以下命令以與 GPIO 互動：

1. 使用 `gpiodetect` 和 `gpioinfo` 命令列出 GPIO 晶片和線路。以下範例呈現 GPIO 晶片資訊：

sh-5.2# ./gpiodetect
        gpiochip0 [c440000.spmi:pmic@8:pinctrl@c00] (12 lines)
        gpiochip1 [c440000.spmi:pmic@1:gpio@8800] (10 lines)
        gpiochip2 [c440000.spmi:pmic@2:gpio@8800] (9 lines)
        gpiochip3 [c440000.spmi:pmic@0:gpio@b000] (4 lines)
        gpiochip4 [f100000.pinctrl] (176 lines)
        gpiochip5 [33c0000.pinctrl] (15 lines)
        Copy to clipboard

    以下範例呈現 GPIO 線路：

sh-5.2# ./gpioinfo gpiochip5
        gpiochip5 - 15 lines:
              line    0:      unnamed       unused   input   active-high
              line    1:      unnamed       unused   input   active-high
              line    2:      unnamed       unused   input   active-high
              line    3:      unnamed       unused   input   active-high
              line    4:      unnamed       unused   input   active-high
              line    5:      unnamed       unused   input   active-high
              line    6:      unnamed       unused   input   active-high
              line    7:      unnamed       unused   input   active-high
              line    8:      unnamed       unused   input   active-high
              line    9:      unnamed       unused   input   active-high
              line   10:      unnamed       unused   input   active-high
              line   11:      unnamed       unused   input   active-high
              line   12:      unnamed       unused   input   active-high
              line   13:      unnamed       unused   input   active-high
              line   14:      unnamed       unused   input   active-high
        Copy to clipboard
2. 使用 `gpioset` 命令設定 GPIO 值。例如，若要在 `gpiochip4` 上設定 `GPIO line 0`，請執行以下操作：

sh-5.2# ./gpioset gpiochip4 0=1
        sh-5.2# ./gpioinfo gpiochip4
        gpiochip4 - 176 lines:
           line    0:      unnamed       unused   output  active-high
           line    1:      unnamed       unused   input   active-high
        Copy to clipboard
3. 使用 `gpioget` 命令讀取 GPIO 值。例如，若要在 `gpiochip4` 上讀取 `GPIO line 0` 的值，請執行以下操作：

sh-5.2# ./gpioget gpiochip4 0
        1
        sh-5.2# ./gpioinfo gpiochip4
        gpiochip4 - 176 lines:
                 line    0:      unnamed       unused   input   active-high
                 line    1:      unnamed       unused   input   active-high
        Copy to clipboard

Last Published: Jan 01, 2026

[Previous Topic
配置動態電壓和頻率縮放 (DVFS) 調節器](https://docs.qualcomm.com/bundle/publicresource/80-70020-3TC/topics/dynamic-clock-and-voltage-scaling-dcvs.md) [Next Topic
即時 (RT) 核心概覽](https://docs.qualcomm.com/bundle/publicresource/80-70020-3TC/topics/real_time_kernel_overview.md)