VAR-SOM-MX6 GPIO
Contents
1 GPIO state
The current state of the system's GPIOs can be obtained in user-mode, as shown in the following example:
root@var-som-mx6:~# cat /sys/kernel/debug/gpio GPIOs 0-31, platform/209c000.gpio, 209c000.gpio: gpio-25 (phy-reset ) out lo GPIOs 32-63, platform/20a0000.gpio, 20a0000.gpio: GPIOs 64-95, platform/20a4000.gpio, 20a4000.gpio: gpio-77 (ov5640_mipi_pwdn ) out lo gpio-86 (usb_otg_vbus ) out lo GPIOs 96-127, platform/20a8000.gpio, 20a8000.gpio: gpio-101 (tlv320aic3x reset ) out lo gpio-106 (ov5640_mipi_reset ) out lo gpio-110 (2194000.usdhc cd ) in hi gpio-111 (2194000.usdhc ro ) in hi gpio-120 (spi_imx ) out lo gpio-121 (ads7846_pendown ) in hi GPIOs 128-159, platform/20ac000.gpio, 20ac000.gpio: gpio-141 (PCIe reset ) out lo GPIOs 160-191, platform/20b0000.gpio, 20b0000.gpio: gpio-178 (sysfs ) out lo GPIOs 192-223, platform/20b4000.gpio, 20b4000.gpio: gpio-200 (wlan-en-regulator ) out lo
Each GPIO is defined as in or out and the state is shown as lo or hi.
For example pin 110 is the SD card card-detect.
When an SD card is plugged in, the state will be:
gpio-110 (2194000.usdhc cd ) in lo
When the SD card is removed, the state will be:
gpio-110 (2194000.usdhc cd ) in hi
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.
GPIO7_4 will be (7-1)*32+4=196.
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 196 > /sys/class/gpio/export
To configure as output:
# echo out > /sys/class/gpio/gpio196/direction
Set GPIO high:
# echo 1 > /sys/class/gpio/gpio196/value
Set GPIO low:
# echo 0 > /sys/class/gpio/gpio196/value
To configure as input:
# echo in > /sys/class/gpio/gpio196/direction
Read the current value:
# cat /sys/class/gpio/gpio196/value
To free the GPIO after you're done using it:
# echo 196 > /sys/class/gpio/unexport
2.2 Manage GPIO from 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(7, 4); /* Just an example */ fd = open("/sys/class/gpio/export", O_WRONLY); sprintf(buf, "%d", gpio); write(fd, buf, strlen(buf)); close(fd);
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); close(fd);
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); close(fd);
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 */ } close(fd);
Once finished, free (unexport) the GPIO:
fd = open("/sys/class/gpio/unexport", O_WRONLY); sprintf(buf, "%d", gpio); write(fd, buf, strlen(buf)); close(fd);
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 arch/arm/boot/dts/ of the Linux kernel source you will find the pin functions definitions files.
The relevant files are imx6dl-pinfunc.h and imx6q-pinfunc.h, depending on the platform you are using.
For example, if you edit imx6q-pinfunc.h and search for GPIO7_IO04, you will see a group of of definitions with same prefix (pad name), "MX6QDL_PAD_SD3_DAT0".
#define MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x2c0 0x6a8 0x000 0x0 0x0 #define MX6QDL_PAD_SD3_DAT0__UART1_CTS_B 0x2c0 0x6a8 0x000 0x1 0x0 #define MX6QDL_PAD_SD3_DAT0__UART1_RTS_B 0x2c0 0x6a8 0x91c 0x1 0x2 #define MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX 0x2c0 0x6a8 0x000 0x2 0x0 #define MX6QDL_PAD_SD3_DAT0__GPIO7_IO04 0x2c0 0x6a8 0x000 0x5 0x0
Adding only the one with the GPIO7_IO04 suffix (function) to your dts file will let you use the pin as GPIO.
3.1.2 Variscite dts files
Variscite defines dts file for each platform.
Device Tree Name |
Include dtsi file |
SOM type |
Carrier Board type |
LCD Type |
Evaluation Kit name |
---|---|---|---|---|---|
imx6q-var-som.dts | imx6qdl-var-som.dtsi | VAR-SOM-MX6_V2 (Quad / Dual) | VAR-MX6CustomBoard | Capacitive/Resistive touch | VAR-DVK-MX6_V2-PRO VAR-STK-MX6_V2 |
imx6q-var-som-vsc.dts | imx6qdl-var-som.dtsi | VAR-SOM-MX6_V2 (Quad / Dual) | VAR-SOLOCustomBoard | Capacitive LVDS touch | N/A |
imx6dl-var-som.dts | imx6qdl-var-som.dtsi | VAR-SOM-MX6_V2 (DualLite/ Solo) | VAR-MX6CustomBoard | Capacitive/Resistive touch | N/A |
imx6dl-var-som-solo-vsc.dts | imx6qdl-var-som.dtsi | VAR-SOM-SOLO / VAR-SOM-DUAL | VAR-SOLOCustomBoard | Capacitive LVDS touch | VAR-DVK-SOLO/DUAL VAR-STK-SOLO/DUAL |
imx6dl-var-som-solo.dts | imx6qdl-var-som.dtsi | VAR-SOM-SOLO / VAR-SOM-DUAL | VAR-MX6CustomBoard | Capacitive/Resistive touch | N/A |
imx6q-var-dart.dts | imx6qdl-var-dart.dtsi | VAR-SOM-SOLO / VAR-SOM-DUAL | VAR-DT6CustomBoard | Capacitive LVDS touch | VAR-STK-DT6.VAR-DVK-DT6 |
imx6q-var-som.dts starts with definitions and includindg dtsi files.
#define VAR_SOM_MX6 #include "imx6q.dtsi" #include "imx6qdl-var-som.dtsi"
The imx6q.dtsi define the CPU platform and which pinfunc file will be included. This feature allow the pin name to be agnostic to the CPU type (i.MX6Q vs i.MX6DL)
imx6qdl-var-som.dtsi has the major VAR-SOM-MX6 definitions.
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/arm/boot/dts/imx6qdl-var-som.dtsi (or imx6qdl-var-dart.dtsi in case of DART-MX6) and add the definition for the GPIO you need in the section below.
pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; imx6qdl-var-som-mx6 { pinctrl_hog: hoggrp { fsl,pins = < /* PMIC INT */ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* Wifi Slow Clock */ MX6QDL_PAD_ENET_RXD0__OSC32K_32K_OUT 0x000b0 /* Audio Clock */ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* Camera Clock */ MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x130b0 MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x0b0b1 MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x0b0b1 >; };
3.2.1 Device Tree GPIO attribute
If you look at Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt in the Linux kernel source tree, the number to the right of the pin control spec can be used for additional attributes like pull-ups, pull-downs, keepers, drive strength, etc.
The value 0x80000000 is "don't know value please use the default". Otherwise, the value consists of a bitwise-OR combination of the following values.
CONFIG bits definition |
value |
---|---|
PAD_CTL_HYS | (1 << 16) |
PAD_CTL_PUS_100K_DOWN | (0 << 14) |
PAD_CTL_PUS_47K_UP | (1 << 14) |
PAD_CTL_PUS_100K_UP | (2 << 14) |
PAD_CTL_PUS_22K_UP | (3 << 14) |
PAD_CTL_PUE | (1 << 13) |
PAD_CTL_PKE | (1 << 12) |
PAD_CTL_ODE | (1 << 11) |
PAD_CTL_SPEED_LOW | (1 << 6) |
PAD_CTL_SPEED_MED | (2 << 6) |
PAD_CTL_SPEED_HIGH | (3 << 6) |
PAD_CTL_DSE_DISABLE | (0 << 3) |
PAD_CTL_DSE_240ohm | (1 << 3) |
PAD_CTL_DSE_120ohm | (2 << 3) |
PAD_CTL_DSE_80ohm | (3 << 3) |
PAD_CTL_DSE_60ohm | (4 << 3) |
PAD_CTL_DSE_48ohm | (5 << 3) |
PAD_CTL_DSE_40ohm | (6 << 3) |
PAD_CTL_DSE_34ohm | (7 << 3) |
PAD_CTL_SRE_FAST | (1 << 0) |
PAD_CTL_SRE_SLOW | (0 << 0) |
3.3 Device Tree GPIO default Value
The Bluetooth is a good example to see how to set the default value during boot.
variscite-bluetooth
For example how to reset the Bluetooth:
echo 178 >/sys/class/gpio/export echo "out" > /sys/class/gpio/gpio178/direction echo 0 > /sys/class/gpio/gpio178/value sleep 1 echo 1 > /sys/class/gpio/gpio178/value sleep 1
You can also add it to your default build file system: initscripts