RK3588 Platform Driver Debugging [GPIO] - RK3588-Operation Control of GPIO

1 Introduction

2. GPIO configuration

The ID of Rockchip Pin is composed of controller (bank) + port (port) + index number (pin)

2.1 GPIO driver introduction

Drivers include Pinctrl driver ( drivers/pinctrl/pinctrl-rockchip.c ) and GPIO driver
( drivers/gpio/gpio-rockchip.c )

  • Pinctrl driver is the main driver, providing IO method set
  • GPIO driver is to complete the function of gpiochip, including GPIO and IRQ

2.2 GPIO multiplexing

RK3588 has 5 GPIO controllers, each controller can control 32 IOs. When used as a GPIO function, the port behavior is configured by the GPIO controller register

  • The number of controllers and GPIO controllers is the same
  • Ports fixed A, B, C and D
  • The index sequence number is fixed 0, 1, 2, 3, 4, 5, 6, 7

If there are multiple multiplexed pins in the same controller, they are generally called m0, m1, m2, etc., such as PWM function:

	pwm1 {
		/omit-if-no-ref/
		pwm1m0_pins: pwm1m0-pins {
			rockchip,pins =
				/* pwm1_m0 */
				<0 RK_PC0 3 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		pwm1m1_pins: pwm1m1-pins {
			rockchip,pins =
				/* pwm1_m1 */
				<1 RK_PD3 11 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		pwm1m2_pins: pwm1m2-pins {
			rockchip,pins =
				/* pwm1_m2 */
				<1 RK_PA3 11 &pcfg_pull_none>;
		};
	};

A Pin can be reused for multiple functions. For example, the GPIO0-C0 pin of pwm1 can be reused as the following pins:

PDM0_CLK0_M1/PWM1_M0/I2C2_SDA_M0/CAN0_RX_M0/SPI0_MOSI_M0/PCIE30X1_0_CLKREQN_M0/GPIO0_C0_d

2.3 Introduction to DTS

Dts generally places the pinctrl node in soc.dtsi, such as rk3588s.dtsi, which is usually located in the last node. In this file, you can find all the configurable function pins of the board.

aliases {
		csi2dcphy0 = &csi2_dcphy0;
		csi2dcphy1 = &csi2_dcphy1;
		csi2dphy0 = &csi2_dphy0;
		csi2dphy1 = &csi2_dphy1;
		csi2dphy2 = &csi2_dphy2;
		dsi0 = &dsi0;
		dsi1 = &dsi1;
		ethernet1 = &gmac1;
		gpio0 = &gpio0;
		gpio1 = &gpio1;
		gpio2 = &gpio2;
		gpio3 = &gpio3;
		gpio4 = &gpio4;
		i2c0 = &i2c0;
		i2c1 = &i2c1;
		i2c2 = &i2c2;
		i2c3 = &i2c3;
		i2c4 = &i2c4;
		i2c5 = &i2c5;
		i2c6 = &i2c6;
		i2c7 = &i2c7;
		i2c8 = &i2c8;
		rkcif_mipi_lvds0= &rkcif_mipi_lvds;
		rkcif_mipi_lvds1= &rkcif_mipi_lvds1;
		rkcif_mipi_lvds2= &rkcif_mipi_lvds2;
		rkcif_mipi_lvds3= &rkcif_mipi_lvds3;
		rkvenc0 = &rkvenc0;
		rkvenc1 = &rkvenc1;
		jpege0 = &jpege0;
		jpege1 = &jpege1;
		jpege2 = &jpege2;
		jpege3 = &jpege3;
		serial0 = &uart0;
		serial1 = &uart1;
		serial2 = &uart2;
		serial3 = &uart3;
		serial4 = &uart4;
		serial5 = &uart5;
		serial6 = &uart6;
		serial7 = &uart7;
		serial8 = &uart8;
		serial9 = &uart9;
		spi0 = &spi0;
		spi1 = &spi1;
		spi2 = &spi2;
		spi3 = &spi3;
		spi4 = &spi4;
		spi5 = &sfc;
		hdcp0 = &hdcp0;
		hdcp1 = &hdcp1;
	};

Finally, the arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi file is added to rk3588s.dtsi in the include form.
The rk3588s-pinctrl.dtsi file has enumerated all iomux instances of the rk3588s chip. Generally, each module no longer needs to create an iomux instance;
creating an iomux instance needs to follow the following rules:

  1. Must be under the pinctrl node
  2. Must be added in the form of function+group
  3. The format of function+group is as follows
function {
	group {
		rockchip,pin = <bank gpio func &ref>;
		};
};

For example, I add the following instructions for using the gpio port

&pinctrl {
	leds {
		led_rgb_b: led-rgb-b {
			rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
	hym8563 {
		rtc_int: rtc-int {
			rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

When using a certain gpio port, you should pay attention to whether other functions refer to this io port.

2.3.1 Modify gpio port

If we need to modify the default pin gpio0c0 of pwm1 to gpio1d3

pwm1: pwm@fd8b0010 {
  compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
  reg = <0x0 0xfd8b0010 0x0 0x10>;
  #pwm-cells = <3>;
  pinctrl-names = "active";
  pinctrl-0 = <&pwm1m0_pins>;
  clocks = <&cru 677>, <&cru 676>;
  clock-names = "pwm", "pclk";
  status = "disabled";
 };
 &pwm1 {
 status = "okay";
};
&pwm1 {
 pinctrl-0 = <&pwm1m1_pins>;
 status = "okay";
};

2.3.2 Configure a certain GPIO level

There are individual requirements that a GPIO does not belong to a specific module, but is more of a power switch. It is hoped that a high or low level will be output as soon as possible after the system is turned on. Use "regulator-fixed". Regulator-fixed is usually used to define A regulator with a fixed voltage, or a regulator controlled by a GPIO switch.
Taking MIPI screen power enable as an example, the gpio port is gpio1c4

vcc_lcd_mipi1: vcc-lcd-mipi1 {   
		status = "okay";
		compatible = "regulator-fixed";
		regulator-name = "vcc_lcd_mipi1";
		gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>;
		enable-active-high;
		regulator-boot-on;
		regulator-state-mem {
			regulator-off-in-suspend;
		};
	};
	

3. Control GPIO under Linux

When compiling the kernel, add Device Drivers->GPIO Support->/sys/class/gpio/… (sysfs interface).
insert image description here

To control GPIO through sysfs, first access the /sys/class/gpio directory and write the GPIO number to the export file, so that the GPIO operating interface is exposed from the kernel space to the user space. The GPIO operating interface includes direction and value, etc., direction control GPIO direction, and value can control GPIO output or obtain GPIO input
/sys/class/gpio. For instructions, please refer to this article: Linux system controls gpio based on syfs

File IO mode operates GPIO, using four functions open, close, read, and write. The following is a simple sample code based on C language for running water light and breathing light effects. This example code uses userspace GPIO control on Linux, you will need to adapt the code to use the correct GPIO pins and paths.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define LED_NUM 4

// GPIO 控制的相关路径
#define SYSFS_GPIO_EXPORT "/sys/class/gpio/export"
#define SYSFS_GPIO_DIR_PREFIX "/sys/class/gpio/gpio"
#define SYSFS_GPIO_VALUE_SUFFIX "/value"

// 设置 GPIO 方向
void set_gpio_direction(int gpio, const char *dir) {
    char gpio_path[50];
    sprintf(gpio_path, "%s%d/direction", SYSFS_GPIO_DIR_PREFIX, gpio);
    
    int fd = open(gpio_path, O_WRONLY);
    if (fd == -1) {
        perror("Error opening direction file");
        exit(EXIT_FAILURE);
    }
    write(fd, dir, strlen(dir));
    close(fd);
}

// 控制 GPIO 输出
void set_gpio_value(int gpio, int value) {
    char gpio_path[50];
    sprintf(gpio_path, "%s%d/value", SYSFS_GPIO_DIR_PREFIX, gpio);
    
    int fd = open(gpio_path, O_WRONLY);
    if (fd == -1) {
        perror("Error opening value file");
        exit(EXIT_FAILURE);
    }
    char str_value = value ? '1' : '0';
    write(fd, &str_value, 1);
    close(fd);
}

int main() {
    int leds[LED_NUM] = {17, 18, 19, 20};  // 假设使用的 GPIO 引脚编号
    int i, j;
    
    for (i = 0; i < LED_NUM; i++) {
        // 导出 GPIO
        int export_fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
        if (export_fd == -1) {
            perror("Error opening export file");
            return EXIT_FAILURE;
        }
        char gpio_str[3];
        sprintf(gpio_str, "%d", leds[i]);
        write(export_fd, gpio_str, strlen(gpio_str));
        close(export_fd);
        
        // 设置 GPIO 方向为输出
        set_gpio_direction(leds[i], "out");
    }
    
    while (1) {
        // 流水灯效果
        for (i = 0; i < LED_NUM; i++) {
            set_gpio_value(leds[i], 1);
            usleep(200000);
            set_gpio_value(leds[i], 0);
        }
        
        // 呼吸灯效果
        for (j = 0; j < 100; j++) {
            for (i = 0; i < LED_NUM; i++) {
                set_gpio_value(leds[i], 1);
                usleep(j * j);
            }
            for (i = 0; i < LED_NUM; i++) {
                set_gpio_value(leds[i], 0);
                usleep(j * j);
            }
        }
    }
    
    return 0;
}

The above code examples are for reference only. Actual use requires appropriate modification and testing based on your hardware and system configuration.

ArmSoM product introduction: http://wiki.armsom.org/index.php/ArmSoM-w3

ArmSoM Technology Forum: http://forum.armsom.org/

Guess you like

Origin blog.csdn.net/nb124667390/article/details/132533506