Difference between revisions of "MX8M GPIO"

From Variscite Wiki
Line 2: Line 2:
--> {{#vardefine:RELEASE_PARAM|{{#urlget:release}}}} <!--
--> {{#vardefine:RELEASE_PARAM|{{#urlget:release}}}} <!--
--> {{#lst:Yocto_Platform_Customization|{{#var:RELEASE_PARAM|RELEASE_MORTY_V1.0_DART-MX8M}}}} <!--
--> {{#lst:Yocto_Platform_Customization|{{#var:RELEASE_PARAM|RELEASE_MORTY_V1.0_DART-MX8M}}}} <!--
--> {{PageHeader|DART-MX8M- GPIO}} {{DocImage|category1=DART-MX8M|category2=Yocto}} __toc__
--> {{PageHeader|{{#var:HARDWARE_NAME}} GPIO}} {{DocImage|category1=DART-MX8M|category2=Yocto}} __toc__
= GPIO state =
= GPIO state =

Revision as of 07:27, 28 February 2019


1 GPIO state

The current state of the system's GPIOs can be obtained in user-mode, as shown in the following example:

# cat /sys/kernel/debug/gpio 
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:
 gpio-7   (                    |eth_phy_pwr         ) out lo    
 gpio-9   (                    |phy-reset           ) out hi    

gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
 gpio-38  (                    |sysfs               ) out hi    
 gpio-39  (                    |sysfs               ) out hi    
 gpio-42  (                    |sysfs               ) out hi    
 gpio-43  (                    |enable              ) out hi    
 gpio-44  (                    |cd                  ) in  lo IRQ
 gpio-51  (                    |VSD_3V3             ) out hi    
 gpio-52  (                    |sysfs               ) out lo    

gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:

gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
 gpio-102 (                    |Back                ) in  hi IRQ
 gpio-104 (                    |ov5640_mipi_pwdn    ) out lo    
 gpio-109 (                    |Home                ) in  hi IRQ
 gpio-111 (                    |Down                ) in  hi IRQ
 gpio-113 (                    |eMMC                ) out lo    
 gpio-114 (                    |Up                  ) in  hi IRQ

gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
 gpio-133 (                    |sysfs               ) out lo    
 gpio-137 (                    |spi_imx             ) in  lo    
 gpio-156 (                    |ov5640_mipi_reset   ) out hi

Each GPIO is defined as in or out and the state is shown as lo or hi.
For example pin 44 is the SD card card-detect. When an SD card is plugged in, the state will be:

 gpio-44  (                    |cd                  ) in  lo IRQ

When the SD card is removed, the state will be:

 gpio-44  (                    |cd                  ) in  hi IRQ

2 Manipulating a single GPIO via /sys/class/gpio

2.1 Using a command line or a script

GPIOs in i.MX are grouped in groups of 32 pins.
For example, GPIO1_3 belong to the first group, pin 3. Its absolute number will be 3.
GPIO4_21 will be (4-1)*32+21=117.
Assuming this GPIO is defined in your device tree, the following is an example of how to use it from userspace.

To export the GPIO for userspace use:

$ echo 117 > /sys/class/gpio/export

To configure as output:

$ echo out > /sys/class/gpio/gpio117/direction

Set GPIO high:

$ echo 1 > /sys/class/gpio/gpio117/value

Set GPIO low:

$ echo 0 > /sys/class/gpio/gpio117/value

To configure as input:

$ echo in > /sys/class/gpio/gpio117/direction

Read the current value:

$ cat /sys/class/gpio/gpio117/value

To free the GPIO after you're done using it:

$ echo 117 > /sys/class/gpio/unexport

2.2 Using a C application

All of the command line operations above can be translated to C code:
Reserve (export) the GPIO:

#define IMX_GPIO_NR(port, index)    ((((port)-1)*32)+((index)&31))

int fd;
char buf[MAX_BUF]; 
int gpio = IMX_GPIO_NR(4, 21); /* Just an example */

fd = open("/sys/class/gpio/export", O_WRONLY);

sprintf(buf, "%d", gpio); 

write(fd, buf, strlen(buf));


Set the GPIO direction:

sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);

fd = open(buf, O_WRONLY);

/* Set out direction */
write(fd, "out", 3); 
/* Set in direction */
write(fd, "in", 2); 


In case of out direction set the GPIO value:

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_WRONLY);

/* Set GPIO high status */
write(fd, "1", 1); 
/* Set GPIO low status */
write(fd, "0", 1); 


In case of in direction get the current GPIO value:

char value;

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_RDONLY);

read(fd, &value, 1);

if (value == '0') { 
     /* Current GPIO status low */
} else {
     /* Current GPIO status high */


Once finished, free (unexport) the GPIO:

fd = open("/sys/class/gpio/unexport", O_WRONLY);

sprintf(buf, "%d", gpio);

write(fd, buf, strlen(buf));


Important notes:

  • Remember that after the first read operation the file pointer will move to the next position in the file, so to get a correct value for each read operation you simply have to set the file pointer at the beginning of the file before read by using the following command:
lseek(fd, 0, SEEK_SET);
  • This is only a short example. If you want to use it in your code remember add error handling to it.

3 Kernel Device Tree GPIO configuration

3.1 Device Tree GPIO files

3.1.1 Pin Func files

In the directory include/dt-bindings/pinctrl/ of the Linux kernel source you will find the pin functions definition files.
The relevant file is pins-imx8mm.h.
If you search it for GPIO4_IO2, for example, you will see a group of definitions with same prefix (pad name), "MX8MM_IOMUXC_SAI1_RXD0".

#define MX8MM_IOMUXC_SAI1_RXD0_SAI1_RX_DATA0                                0x164 0x3CC 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI1_RXD0_SAI5_RX_DATA0                                0x164 0x3CC 0x4D4 0x1 0x1
#define MX8MM_IOMUXC_SAI1_RXD0_PDM_DATA0                                    0x164 0x3CC 0x534 0x3 0x1
#define MX8MM_IOMUXC_SAI1_RXD0_CORESIGHT_TRACE0                             0x164 0x3CC 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2                                    0x164 0x3CC 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI1_RXD0_CCMSRCGPCMIX_BOOT_CFG0                       0x164 0x3CC 0x000 0x6 0x0
#define MX8MM_IOMUXC_SAI1_RXD0_SIM_M_HADDR17                                0x164 0x3CC 0x000 0x7 0x0

Adding only the one with the GPIO4_IO2 suffix (function) to your dts file will let you use the pin as GPIO.

3.2 Define a pin as GPIO in the kernel Device Tree

You need to add the relevant definitions to your device tree, as explained in the Pin Func files section above.
Edit arch/arm64/boot/dts/freescale/fsl-imx8mm-var-dart.dts and add the definition for the GPIO you need in the iomuxc node.

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;

	imx8mm-var-dart {
		pinctrl_hog: hoggrp {
			fsl,pins = <
				/* Add your GPIO definitions here */ 

3.2.1 Device Tree GPIO attribute

If you look at pin control definitions in arch/arm64/boot/dts/freescale/fsl-imx8mm-var-dart.dts in the Linux kernel source tree, the number to the right of the pin control spec can be used for additional attributes like pull-up, slew rate, open drain, drive strength, etc. The value is written to IOMUXC_SW_PAD_CTRL_ register of the relevant pin. Please consult processor reference manual for details.