# Đặt cấu hình pinctrl driver

Hệ thống con Pinctrl trong Qualcomm Linux kernel quản lý và đặt cấu hình các chân được dùng cho đầu vào/đầu ra đa năng (GPIO), mạch tích hợp (I2C), giao diện ngoại vi nối tiếp (SPI) và các giao diện phần cứng khác.

Cấu hình Pinctrl, chẳng hạn như **pin muxing** và **pin groupings**, được quản lý trong driver pinctrl dành riêng cho thiết bị, trong đó driver liệt kê tất cả các chân và chức năng hiện có.

Ví dụ: driver tương ứng cho QCS6490 có sẵn trong tệp `kernel-src/drivers/pinctrl/qcom/pinctrl-sc7280.c`.

Ghi chú

Để biết thêm thông tin về driver pinctrl khác của Qualcomm SoC, hãy xem [Pinctrl Drivers](https://github.com/torvalds/linux/tree/master/drivers/pinctrl/qcom).

Sau đây là các đối tượng dữ liệu pinctrl:

Bảng: Đối tượng dữ liệu pinctrl

| Biến | Mô tả |
| --- | --- |
| static const struct pinctrl_pin_desc sc7280_pins<br>    Copy to clipboard | Liệt kê tất cả các chân và tên của chúng |
| static const struct msm_pingroup sc7280_groups<br>    Copy to clipboard | Định nghĩa các chức năng kết hợp hiện có cho nhóm chân GPIO |
| enum sc7280_functions<br>    Copy to clipboard | Liệt kê tất cả các chức năng có sẵn dưới dạng giá trị enum |

Để biết thêm thông tin về các chức năng được hỗ trợ trong tài liệu liên kết pinctrl SoC tương ứng cho QCS6490, hãy xem [pinctrl binding documentation](https://www.kernel.org/doc/Documentation/devicetree/bindings/pinctrl/qcom%2Csc7280-pinctrl.yaml).

**Lựa chọn chức năng**

Đối với đối tượng dữ liệu `sc7280_functions`, một hoặc nhiều chân GPIO được dùng làm chức năng và phải được đăng ký vào device tree và được truyền đến đúng node  thiết bị.

Trong quá trình khởi động hệ thống, cơ sở hạ tầng kernel pinctrl sẽ đăng ký các chức năng.

Ví dụ sau đây mô tả cơ sở hạ tầng cấu hình kernel:

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

## Đặt cấu hình việc sử dụng GPIO

Cấu hình chân GPIO yêu cầu hai cài đặt sau. Các cài đặt định nghĩa trạng thái chân GPIO và cấu hình các chân đó có thể dùng được cho bất kỳ hoạt động đầu vào/đầu ra nào.

- Mux: Cài đặt mux yêu cầu chọn tên hàm được ánh xạ từ tập hợp các hàm có sẵn trong trình điều khiển pinctrl dành riêng cho SoC.

    Để biết thêm thông tin về pinctrl, hãy xem [Cấu hình pinctrl](https://docs.qualcomm.com/doc/80-70020-3VI/topic/pinctrl-configuration.html#pinctrl-configuration).
- Cấu hình: Phần cấu hình yêu cầu thiết lập thuộc độ mạnh truyền dẫn và độ phân cực.

Các ví dụ sau đây mô tả hai cài đặt định nghĩa chân GPIO theo các quy trình sau:

1. Định nghĩa cấu hình chân trong device tree:

bt_en: bt-en-state {
           pins = "gpio85";
           function = "gpio";
           output-low;
           bias-disable;
        };
        Copy to clipboard
2. Đặt cấu hình node thiết bị khối IP trong device tree:

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. Mã driver phải sử dụng API chung để chọn và đăng ký cấu hình GPIO của API trong cấu hình pinctrl.

    Sau đây là một ví dụ về các API hiện có:

> 
> 
> 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 làm yêu cầu ngắt (IRQ)**

Để đặt GPIO làm IRQ, hãy sử dụng quy trình sau:

1. Đặt cấu hình chân GPIO trong tệp DTS:

    1. Đặt thuộc tính và chức năng cho chân GPIO.
    2. Đặt chân để sử dụng GPIO 55 cho hàm `qup_se_l3()` với các cấu hình sau:

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. Tạo mục nhập DT giống như cấu hình trước đó cho node thiết bị mà bạn muốn đặt GPIO làm IRQ.

    Trong ví dụ sau, GPIO55 được đặt cấu hình là IRQ với thiết bị cha là bộ chọn chế độ cấp cao nhất (TLMM) và mức được đặt ở mức cao.

interrupts-extended = <&tlmm 55 IRQ_TYPE_LEVEL_HIGH>;
        Copy to clipboard
3. Driver phải đọc giá trị và đăng ký nó làm lệnh ngắt cho bộ điều khiển ngắt chung (GIC) bằng cách sử dụng API `request_irq` chỉ định thanh ghi dịch vụ ngắt (ISR) và cờ IRQ.

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

## Đặt cấu hình GPIOS để tạo ra tín hiệu xung hoặc điều chế độ rộng xung

Đặt cấu hình bất kỳ GPIO nào với `GP_CLK` làm chức năng thay thế để có khả năng điều chế độ rộng xung (PWM) hoặc xung nhịp.

Ghi chú

Quy trình sau đây áp dụng cho SoC QCS6490.

Để biết thêm thông tin về cách tìm GPIO có chức năng `GP_CLK`, hãy xem [Mô tả chân](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. Thêm node cấu hình GPIO vào tệp `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. Định nghĩa devicetree node trong tệp `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. Thêm đoạn mã sau vào driver:

+#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. Nếu bạn không sử dụng xung nhịp hoặc PWM, hãy gọi `clk_disable_unprepare()` để vô hiệu hóa xung nhịp nhằm tiết kiệm điện năng.

Ghi chú

Đảm bảo gọi `clk_prepare_enable()` trước khi gọi `clk_disable_unprepare()`.
5. Để tạo chu kỳ nhiệm vụ cần thiết, hãy gọi API `clk_set_duty_cycle()` sau API `clk_prepare_enable`.

## Đặt cấu hình GPIOS từ không gian người dùng

Sử dụng thư viện `libgpiod` từ không gian người dùng để điều khiển GPIOS cho hiệu năng tốt hơn.

1. Để biên dịch và đưa thư viện `libgpiod` vào thiết bị từ máy chủ, hãy thực hiện như sau:

    1. Để cài đặt Arm^®^ (Arm64) toolchain, hãy chạy các lệnh sau:

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

sudo apt install binutils-aarch64-linux-gnu
            Copy to clipboard
    2. Để tải xuống và giải nén mã nguồn libgpiod từ [libgpiod 1.6.4.tar.xz](https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-1.6.4.tar.xz), hãy chạy các lệnh sau:

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. Để đặt cấu hình các nguồn cho liên kết tĩnh, hãy chạy lệnh sau:

./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. Để biên dịch thư viện, hãy chạy lệnh sau:

make
            Copy to clipboard

Ghi chú

Việc biên dịch sẽ tạo các tệp nhị phân được liên kết.
    5. Để tạo các tệp nhị phân được liên kết tĩnh, hãy chạy các lệnh sau:

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. Để đưa các tệp nhị phân vào thiết bị của bạn sau khi biên dịch, hãy chạy lệnh `scp`. Ví dụ:

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

Sau khi đẩy các tệp nhị phân vào thiết bị của bạn, hãy chạy các lệnh sau trên thiết bị để tương tác với GPIO:

1. Sử dụng lệnh `gpiodetect` và `gpioinfo` để liệt kê các chip và dòng GPIO. Ví dụ sau đây mô tả thông tin về chip 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

    Ví dụ sau đây mô tả các dòng 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. Sử dụng lệnh `gpioset` để đặt giá trị GPIO. Ví dụ: để đặt `GPIO line 0` trên `gpiochip4`, hãy thực hiện như sau:

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. Sử dụng lệnh `gpioget` để đọc giá trị GPIO. Ví dụ: để đọc giá trị của `GPIO line 0` trên `gpiochip4`, hãy thực hiện như sau:

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
Đặt cấu hình bộ điều chỉnh điện áp và tần số động (DVFS)](https://docs.qualcomm.com/bundle/publicresource/80-70020-3VI/topics/dynamic-clock-and-voltage-scaling-dcvs.md) [Next Topic
Tổng quan về kernel theo thời gian thực (RT)](https://docs.qualcomm.com/bundle/publicresource/80-70020-3VI/topics/real_time_kernel_overview.md)