# pinctrlドライバーを構成する

Qualcomm LinuxカーネルのPinctrlサブシステムは、汎用入出力（GPIO）、インターインテグレーテッド・サーキット（I2C）、シリアル・ペリフェラル・インターフェース（SPI）などのハードウェア・インターフェースに使用するピンを管理および構成します。

pinctrl構成（**ピンの多重化** や **ピンのグループ化** など）はデバイス特有のpinctrlドライバーで管理され、使用可能なピンと機能の一覧が生成されます。

例えば、QCS6490に対応するドライバーは `kernel-src/drivers/pinctrl/qcom/pinctrl-sc7280.c` ファイルから入手できます。

注釈

追加の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 | 使用可能な関数を列挙値としてリストする |

QCS6490の各SoCでサポートされている関数のpinctrl拘束文書については、[pinctrl binding documentation](https://www.kernel.org/doc/Documentation/devicetree/bindings/pinctrl/qcom%2Csc7280-pinctrl.yaml) を参照してください。

**関数選択**

`sc7280_functions` データオブジェクトについて、1つまたは複数の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ピン構成には、以下の2つの設定が必要です。これらの設定はGPIOピンの状態を定義し、これらのピンをどの入出力アクティビティでも使用できるようにします。

- 多重化：多重化設定では、SoC固有のpinctrlドライバーで使用可能な一連の関数からマッピングされた関数名を選択する必要があります。

    pinctrlの詳細については、[pnctrlの構成](https://docs.qualcomm.com/doc/80-70020-3JA/topic/pinctrl-configuration.html#pinctrl-configuration) を参照してください。
- 構成：構成設定では、ドライブの強度とバイアスのプロパティの設定が必要です。

以下の例は、以下の手順を使用してこの2つの設定で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を使用してGPIO構成を選択し、pinctrl構成内で登録する必要があります。

    以下は使用可能な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

**割り込みリクエスト（IRQ）としてのGPIO**

GPIOをIRQとして設定するには、以下の手順に従います。

1. DTSファイルでGPIOピンを構成します。

    1. GPIOピンのプロパティと関数を設定します。
    2. 以下の構成を使用して、`qup_se_l3()` 関数についてGPIO 55を使用するようピンを設定します。

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 を使用して割り込みサービスプロバイダー（ISR）とIRQフラグを指定し、読み取った値を汎用割り込みコントローラー（GIC）に割り込みとして登録する必要があります。

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

## GPIOを構成してクロックまたはパルス幅モジュレーションを生成する

`GP_CLK` をもつ任意のGPIOを代替機能として構成し、クロックまたはパルス幅モジュレーション（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. GPIO構成ノードを `kernel/arch/arm64/boot/dts/qcom/sc7280.dtsi` ファイルに追加します。

> 
> 
> +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_disable_unprepare()` を呼び出す前に、まず `clk_prepare_enable()` を呼び出してください。
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ソースを [libgpiod 1.6.4.tar.xz](https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-1.6.4.tar.xz) からダウンロードおよび抽出するには、以下のコマンドを実行します。

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行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行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-3JA/topics/dynamic-clock-and-voltage-scaling-dcvs.md) [Next Topic
リアルタイム（RT）カーネルの概要](https://docs.qualcomm.com/bundle/publicresource/80-70020-3JA/topics/real_time_kernel_overview.md)