GPIO Control Program Description


1. Overview

This document mainly introduces how to configure padmux on PCUPID to implement GPIO multiplexing function, mainly referring to [GPIO User Guide]".


2. Keywords

dts/dtsi:

Linux device tree files are usually used to describe peripherals supported by the CPU. The attribute values contained in the peripheral nodes can be used to configure the peripherals.

padmux:

Pin multiplexing is used to connect the module function pins to specific external pins to open up signal connections.

Table 1: PCUPID GPIO index and PAD correspondence table

Pad Name GPIO Index Pad Name GPIO Index Pad Name GPIO Index Pad Name GPIO Index
PAD_UART0_TX 0 PAD_GPIOE_28 37 PAD_GPIOB_04 74 PAD_SAR_ADC0_05 111
PAD_PWM_OUT00 1 PAD_GPIOA_00 38 PAD_GPIOB_05 75 PAD_SAR_ADC0_06 112
PAD_PWM_OUT01 2 PAD_GPIOA_01 39 PAD_GPIOB_06 76 PAD_SAR_ADC0_07 113
PAD_SPI_CK 3 PAD_GPIOA_02 40 PAD_GPIOB_07 77 PAD_SAR_ADC0_08 114
PAD_SPI_HLD 4 PAD_GPIOA_03 41 PAD_GPIOB_08 78 PAD_SAR_ADC0_09 115
PAD_SPI_CZ 5 PAD_GPIOA_04 42 PAD_OUTP_RX0_CH0 79 PAD_SAR_ADC0_10 116
PAD_SPI_WPZ 6 PAD_GPIOA_05 43 PAD_OUTN_RX0_CH0 80 PAD_SAR_ADC0_11 117
PAD_SPI_DI 7 PAD_GPIOA_06 44 PAD_OUTP_RX0_CH1 81 PAD_SAR_ADC0_12 118
PAD_SPI_DO 8 PAD_GPIOA_07 45 PAD_OUTN_RX0_CH1 82 PAD_SAR_ADC0_13 119
PAD_GPIOE_00 9 PAD_GPIOA_08 46 PAD_OUTP_RX0_CH2 83 PAD_SAR_ADC0_14 120
PAD_GPIOE_01 10 PAD_GPIOA_09 47 PAD_OUTN_RX0_CH2 84 PAD_PWM_ADC01 121
PAD_GPIOE_02 11 PAD_GPIOA_10 48 PAD_OUTP_RX0_CH3 85 PAD_PWM_ADC00 122
PAD_GPIOE_03 12 PAD_GPIOA_11 49 PAD_OUTN_RX0_CH3 86 PAD_GPIOD_01 123
PAD_GPIOE_04 13 PAD_EMMC_RST 50 PAD_GPIOC_00 87 PAD_GPIOD_02 124
PAD_GPIOE_05 14 PAD_EMMC_CLK 51 PAD_GPIOC_01 88 PAD_GPIOD_03 125
PAD_GPIOE_06 15 PAD_EMMC_CMD 52 PAD_GPIOC_02 89 PAD_GPIOD_00 126
PAD_GPIOE_07 16 PAD_EMMC_DS 53 PAD_GPIOC_03 90 PAD_UART0_RX 127
PAD_GPIOE_08 17 PAD_EMMC_D3 54 PAD_GPIOC_04 91 PAD_PM_GPIO4 128
PAD_GPIOE_09 18 PAD_EMMC_D4 55 PAD_GPIOC_05 92 PAD_PM_GPIO5 129
PAD_GPIOE_10 19 PAD_EMMC_D0 56 PAD_GPIOC_06 93 PAD_PM_PWM1_OUT 130
PAD_GPIOE_11 20 PAD_EMMC_D5 57 PAD_GPIOC_07 94 PAD_PM_I2C_SDA 131
PAD_GPIOE_12 21 PAD_EMMC_D1 58 PAD_GPIOC_08 95 PAD_PM_PWM0_OUT 132
PAD_GPIOE_13 22 PAD_EMMC_D6 59 PAD_OUTP_CH0 96 PAD_PM_I2C_SCL 133
PAD_GPIOE_14 23 PAD_EMMC_D2 60 PAD_OUTN_CH0 97 PAD_PM_GPIO1 134
PAD_GPIOE_15 24 PAD_EMMC_D7 61 PAD_OUTP_CH1 98 PAD_PM_GPIO3 135
PAD_GPIOE_16 25 PAD_GPIOA_12 62 PAD_OUTN_CH1 99 PAD_PM_UART1_TX 136
PAD_GPIOE_17 26 PAD_GPIOA_13 63 PAD_OUTP_CH2 100 PAD_PM_GPIO2 137
PAD_GPIOE_18 27 PAD_GPIOA_14 64 PAD_OUTN_CH2 101 PAD_PM_GPIO7 138
PAD_GPIOE_19 28 PAD_GPIOA_15 65 PAD_OUTP_CH3 102 PAD_PM_GPIO6 139
PAD_GPIOE_20 29 PAD_GPIOA_16 66 PAD_OUTN_CH3 103 PAD_PM_UART1_RX 140
PAD_GPIOE_21 30 PAD_GPIOA_17 67 PAD_OUTP_CH4 104 PAD_PM_ADC00_IN 141
PAD_GPIOE_22 31 PAD_GPIOA_18 68 PAD_OUTN_CH4 105 PAD_PM_GPIO0 142
PAD_GPIOE_23 32 PAD_GPIOA_19 69 PAD_SAR_ADC0_00 106
PAD_GPIOE_24 33 PAD_GPIOB_00 70 PAD_SAR_ADC0_01 107
PAD_GPIOE_25 34 PAD_GPIOB_01 71 PAD_SAR_ADC0_02 108
PAD_GPIOE_26 35 PAD_GPIOB_02 72 PAD_SAR_ADC0_03 109
PAD_GPIOE_27 36 PAD_GPIOB_03 73 PAD_SAR_ADC0_04 110

3.Uboot configuration

3.1. uboot config is configured as follows

[*] SigmaStar drivers  --->

    [*]   SigmaStar GPIO
    [*]   SigmaStar padmux

3.2. DTS configuration is as follows, compatible is generally not modified, status is configured as okay/disabled as needed.

gpio: gpio {
    compatible = "sstar,gpio";
    tatus = "okay";
};

3.3. Use of uboot cmd

gpio input <gpio#>  --> gpio input 69  // gpio69 set as input
gpio set <gpio#>    --> gpio set 10    // gpio10 set as output high
gpio clear <gpio#>  --> gpio clear 49  // gpio49 set as output low
gpio toggle <gpio#> --> gpio toggle 49 // gpio49 level toggle
gpio status <gpio#> --> gpio status 20 // gpio20 status

4.1. kernel config configuration instructions

Device Drivers  --->

    [*] GPIO Support  --->
        [*]   /sys/class/gpio/... (sysfs interface)

    [*] SStar SoC platform drivers  --->
        [*]   Sstar GPIO driver
        [*]   Sstar PADMUX driver

4.2. dts parameter configuration instructions

gpio: gpio {
    compatible = "sstar,gpio";
    #gpio-cells = <2>;
    status = "okay";
};
Properties Description Notes
compatible Used to match the driver for driver registration Modification is prohibited
#gpio-cells Declare the number of device node gpio cells Configuring 2 means the first cell is the gpio number, and the second cell indicates the gpio effective level
status Driver switch Configure as needed, ok/disabled

5. Introduction to reuse functions

When you need to use the GPIO multiplexing function, you first need to obtain the name of the PIN to be operated and the mux mode to be multiplexed, and configure them in xxx-padmux.dtsi:

<PAD_GPIOC_02            PINMUX_FOR_I2S0_MCK_MODE_1       MDRV_PUSE_I2S0_MCK>,
<PAD_GPIOC_03            PINMUX_FOR_I2S0_RX_MODE_1        MDRV_PUSE_I2S0_RX_BCK>,
<PAD_GPIOC_04            PINMUX_FOR_I2S0_RX_MODE_1        MDRV_PUSE_I2S0_RX_WCK>,
<PAD_GPIOC_05            PINMUX_FOR_I2S0_RX_MODE_1        MDRV_PUSE_I2S0_RX_SDI>,
<PAD_GPIOC_06            PINMUX_FOR_I2S0_TX_MODE_1        MDRV_PUSE_I2S0_TX_SDO>,
<PAD_GPIOC_07            PINMUX_FOR_I2S0_TX_MODE_1        MDRV_PUSE_I2S0_TX_BCK>,
<PAD_GPIOC_08            PINMUX_FOR_I2S0_TX_MODE_1        MDRV_PUSE_I2S0_TX_WCK>,

As shown in the above I2S0 configuration, the first column is the pad name, which can be obtained from Table 1 (or refer to /drivers/sstar/include/pcupid/gpio.h), the second column indicates the pad multiplexing mode (refer to /drivers/sstar/include/pcupid/padmux.h), and the third column is the name of the current padmux configuration (refer to /drivers/sstar/include/drv_puse.h), which is also the function of the pad in the current mode.

Taking PAD_GPIOC_02 as an example, the modes it supports are shown in Table 2. When the pad is used as the MCLK output master clock signal of I2S0, it needs to be configured as PINMUX_FOR_I2S0_MCK_MODE_1 ; and when used as PWM2, it needs to be configured as PINMUX_FOR_PWM2_MODE_1 .

Table 2: List of modes supported by PAD_GPIOC_02

mode mode mode
PINMUX_FOR_GPIO_MODE PINMUX_FOR_FUART_MODE_2 PINMUX_FOR_FUART_2W_MODE_2
PINMUX_FOR_I2S0_MCK_MODE_1 PINMUX_FOR_BT656_OUT_MODE_1 PINMUX_FOR_TTL24_MODE_1
PINMUX_FOR_TTL18_MODE_1 PINMUX_FOR_TTL18_MODE_2 PINMUX_FOR_TTL16_MODE_1
PINMUX_FOR_TTL16_MODE_2 PINMUX_FOR_TTL_SRGB8_MODE_1 PINMUX_FOR_LCD8_MODE_1
PINMUX_FOR_LCD16_MODE_1 PINMUX_FOR_LCD18_MODE_1 PINMUX_FOR_PWM2_MODE_1
PINMUX_FOR_IR2_IN_MODE_1 PINMUX_FOR_PSPI0_G_MODE_1 PINMUX_FOR_PSPI1_4W_MODE_2

After the configuration is complete, you need to check whether other pads are configured in the same mode, or the same pad is configured in another mode. This will cause conflicts and may make the configured padmux invalid. You need to comment it out or reselect the pad.

// Take DMIC as an example to demonstrate the conflict situation
//SDMMC1
...
<PAD_GPIOA_07 PINMUX_FOR_GPIO_MODE MDRV_PUSE_SDIO0_PWR>,
...
//DMIC
<PAD_GPIOA_07 PINMUX_FOR_DMIC_8CH_MODE_3 MDRV_PUSE_DMIC0_CLK>,
...

As shown above, the PAD_GPIO_07 pin is configured in dtsi at the same time, and is configured in GPIO mode and DMIC respectively, used as SDIO pwr and DMIC clk. If one of the configurations is not commented out, one of the configured functions is destined to be due to pin conflict. It is not available.

To summarize the things to note:

  • A pad can only be configured in one mode. If multiple modes are configured, conflicts will occur.

  • One MDRV_PUSE_XXX can only correspond to one set of pad configurations. There cannot be multiple sets of the same MDRV_PUSE_XXX configurations, otherwise there will be conflicts;

  • The configured pad and mode need to correspond.


6. Sample code

The user space control gpio code is as follows:

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

#define GPIO_93_PIN   "93"
#define GPIO_DIR_VAL  "out"
#define GPIO_VAL_H    "1"
#define GPIO_VAL_L    "0"

int main(int argc, char *argv[])
{
    char buff[2] = {0};
    int gpio_val_fd = 0;
    int gpio_dir_fd = 0;
    int gpio_export_fd = 0;
    int pin_val = 0;

    gpio_export_fd = open("/sys/class/gpio/export", O_WRONLY);
    if (gpio_export_fd < 0)
    {
        printf("open gpio export failed\n");
        return -1;
    }
    else
    {
        write(gpio_export_fd, GPIO_93_PIN, sizeof(GPIO_93_PIN));
    }

    gpio_dir_fd = open("/sys/devices/gpiochip0/gpio/gpio93/direction", O_RDWR);
    if (gpio_val_fd < 0)
    {
        close(gpio_export_fd);
        printf("open direction failed\n");
        return -2;
    }

    write(gpio_dir_fd, GPIO_DIR_VAL, sizeof(GPIO_DIR_VAL));

    gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR);
    if (gpio_val_fd == -1)
    {
        printf("gpio open failed\n");
        close(gpio_export_fd);
        close(gpio_dir_fd);
        return -3;
    }
    else
    {
        printf("/sys/class/gpio/gpio93/value\n");
    }

    memset(buff, 0, 2);
    read(gpio_val_fd, buff, 1);
    pin_val = atoi(buff);
    printf("first read gpio val %d, %s\n", pin_val, buff);
    write(gpio_val_fd, GPIO_VAL_H, sizeof(GPIO_VAL_H));

    close(gpio_val_fd);
    gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR);

    memset(buff, 0, 2);
    read(gpio_val_fd, buff, 1);
    pin_val = atoi(buff);
    printf("after write 1,second read gpio val %d, %s\n", pin_val, buff);

    write(gpio_val_fd, GPIO_VAL_L, sizeof(GPIO_VAL_L));
    close(gpio_val_fd);
    gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR);

    memset(buff, 0, 2);
    read(gpio_val_fd, buff, 1);
    pin_val = atoi(buff);
    printf("after write 0, third read gpio val %d, %s\n", pin_val, buff);

    close(gpio_export_fd);
    close(gpio_dir_fd);
    close(gpio_val_fd);

    return 0;
}

GPIO 93 corresponds to PAD_GPIOC_06, and the padmux configuration is as PINMUX_FOR_GPIO_MODE shown below:

<PAD_GPIOC_06 PINMUX_FOR_GPIO_MODE MDRV_PUSE_PSPI1_CS>,

In the demo, the controlled GPIO pin is first written to /sys/class/gpio/export, then /sys/devices/gpiochip0/gpio/gpio93/direction is set to output, the output level value is written to /sys/class/gpio/gpio93/value as 1, the pin value is read and then 0 is written, and finally the level value is read again.