GPIO access from kernel space

Am using a platform driver to access the external memory interface (EIM). In this kernel driver I want to write to RGMII_RD1 pin to trigger RESET_OUT from Kernel space, but I don’t know how to access it.

According to GPIO access from kernel space I can use the API of linux/gpio.h

int gpio_request(unsigned int gpio, const char *label);
void gpio_free(unsigned int gpio);
int gpio_direction_input(unsigned int gpio);
int gpio_direction_output(unsigned int gpio, int value);
int gpio_get_value(unsigned int gpio);
void gpio_set_value(unsigned int gpio, int value);

According to GPIO in the kernel: an introduction

In current kernels, every GPIO in the system is represented by a simple unsigned integer. There is no provision for somehow mapping a desired function (“the sensor power line for the first camera device,” say) onto a GPIO number; the code must come by that knowledge by other means. Often that is done through a long series of macro definitions; it is also possible to pass GPIO numbers through platform data or a device tree.

How can I find out the GPIO number using the device tree?

I know that I can get custom properties from the device tree using the API of linux/of.h, e.g.

int of_property_read_u32_index(const struct device_node *np,
				       const char *propname,
				       u32 index, u32 *out_value)

I know that RGMII_RD1 is pin 27 on the gpio6 bank. But neither know how to read this information from the device tree, nor do I know how to convert this information into the “simple unsigned integer” representing this GPIO.

I can answer the part of my question about the “simple unsigned integer” representing this GPIO myself. It is as stated in GPIO Alphanumeric to GPIO Numeric Assignment

32 x (controller- 1) + gpio = 32 * (6 - 1) + 27 = 187

Now the remaining question is:

How can I read the gpio bank and and pin number from the device tree?


E.g. the PWM backlight driver uses a GPIO for ON/OFF in addition to the PWM pin.

Have a look here for a standard way of representing a GPIO is done in the device tree.

  • The pinctrl-0 property is used to specify the muxing of all pins used by the driver. Generic code will request and mux the pins before your drivers probe() is called.

  • A property ending in ‘-gpios’ in its name is used to specify one or more pins that are to be used as gpios. e.g.

    enable-gpios = <&gpio3 26 GPIO_ACTIVE_HIGH>;
    This property then gets read in your drivers probe function and its value stored in your drivers data structure. e.g. for the backlight-pwm driver case here.


Thank you.

What I still miss is the meaning of &pinctrl_gpio_bl_on in:

pinctrl-0 = <&pinctrl_gpio_bl_on>;

I see that it is a reference to

	pinctrl_gpio_bl_on: gpio-bl-on {
		fsl,pins = <

MX6QDL_PAD_EIM_D26__GPIO3_IO26 is defined in arch/arm/boot/dts/imx6dl-pinfunc.h and there I found:

#define MX6QDL_PAD_RGMII_RD1__HSI_TX_FLAG           0x2b0 0x698 0x000 0x0 0x0
#define MX6QDL_PAD_RGMII_RD1__RGMII_RD1             0x2b0 0x698 0x81c 0x1 0x1
#define MX6QDL_PAD_RGMII_RD1__GPIO6_IO27            0x2b0 0x698 0x000 0x5 0x0

I guess these are different modes for PAD_RGMII_RD1?
So I need MX6QDL_PAD_RGMII_RD1__GPIO6_IO27 I guess?

I tried to by appending this to my dts file:

/ {
	pinctrl_reset: reset {
		fsl,pins = <

	reset-out {
		compatible = "pe-abcc";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_reset>;
		reset-gpios = <&gpio6 27 GPIO_ACTIVE_HIGH>;
		status = "disabled";

and in my platform device probe function I added (using the newer GPIO API):

	reset_pin = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);

	if (IS_ERR(reset_pin)) {
		ret = PTR_ERR(reset_pin);
		printk("gpiod_get error %i\n", ret);
		goto err_cdev_add;

But probing fails:

# modprobe pe_abcc
[   54.535286] gpiod_get error -2
[   54.539077] pe_abcc: probe of c000000.sram failed with error -2

What am I missing?


Got it!

I added the device tree entries at the wrong places. The pinctrl_reset definition belongs into section &iomuxc, the other entries belong into the section of the corresponding device the driver is written for. In my case &weimsram@2,0. Here is the diff:

diff --unified arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts arch/arm/boot/dts/imx6dl-colibri-pe641t-1.dts
--- arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts        2017-11-07 16:37:29.822747571 +0100
+++ arch/arm/boot/dts/imx6dl-colibri-pe641t-1.dts       2017-11-10 10:39:19.451441583 +0100
@@ -217,6 +217,11 @@
                                MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 PAD_CTRL_HYS_PD /* SODIMM 106 */
+               pinctrl_reset: reset {
+                       fsl,pins = <
+                               MX6QDL_PAD_RGMII_RD1__GPIO6_IO27 PAD_CTRL_HYS_PD/* SODIMM 187 */
+                       >;
+               };

@@ -313,4 +318,17 @@
                fsl,weim-cs-timing = <0x00010081 0x00000000 0x04000000
                                0x00000000 0x04000040 0x00000000>;
+        /* SRAM on CS2 */
+       sram@2,0 {
+               compatible = "cypress,cy7c1019dv33-10zsxi, mtd-ram, pe-abcc";
+               reg = <2 0 0x00010000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               bank-width = <2>;
+               fsl,weim-cs-timing = <0x00810001 0x00000000 0x06000000
+                               0x00000000 0x06000003 0x00000000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reset>;
+               reset-gpios = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+       };