Difference between revisions of "How to control a GPIO in kernel space"

[quality revision] [quality revision]
m
 

Template:ArticleMainWriter Template:ArticleApprovedVersion


1 Purpose[edit]

This article gives an example of a driver that controls GPIOs from kernel space.
Sample source files are provided as examples: kernel module (driver), device tree and Makefile.
This example is available for STM32MP15_Evaluation_boards or STM32MP15_Discovery_kits

2 Code[edit]

2.1 Objective[edit]

Sample gpiolib usage code that makes an LED blink for 20 seconds.

2.2 Device tree[edit]

dummy_device {
   compatible = "st,dummy";
   status = "okay";
   greenled-gpios = <&gpioa 14 0>;
};

See GPIO_device_tree_configuration for more details of GPIO use in a device tree.

2.3 Kernel module code[edit]


#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>

struct gpio_desc *red, *green;

static int gpio_init_probe(struct platform_device *pdev)
{
   int i = 0;

   printk("GPIO example init\n");

   /* "greenled" label is matching the device tree declaration. OUT_LOW is the value at init */
   green = devm_gpiod_get(&pdev-
>dev
>dev, "greenled", GPIOD_OUT_LOW);

   /* blink of the green led */	
   while (i < 10)
   {
	ssleep(1);
	gpiod_set_value(green, 1);

	ssleep(1);
	gpiod_set_value(green, 0);
	
	i++;
   }

   return(0);
}

static int gpio_exit_remove(struct platform_device *pdev)
{
   printk("GPIO example exit\n");
   
   return(0);
}

/* this structure does the matching with the device tree */
/* if it does not match the compatible field of DT, nothing happens */
static struct of_device_id dummy_match[] = {
    {.compatible = "st,dummy"},
    {/* end node */}
};

static struct platform_driver dummy_driver = {
    .probe = gpio_init_probe,
    .remove = gpio_exit_remove,
    .driver = {
        .name = "dummy_driver",
                .owner = THIS_MODULE,
                .of_match_table = dummy_match,
    }
};
 
module_platform_driver(dummy_driver);

MODULE_AUTHOR("Bernard Puel");
MODULE_DESCRIPTION("Gpio example");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dummy_driver");

2.4 Kernel module build[edit]

See Adding_external_out-of-tree_Linux_kernel_modules for further information on module compilation.


2.5 Kernel module use[edit]

PC $> scp dummy_driver.ko root@<board ip address>:/lib/modules/
  • Update dependency descriptions for loadable kernel modules, and synchronize the data on disk with memory
Board $> /sbin/depmod -a
Board $> sync
  • Insert the kernel module example into the Linux kernel
Board $> modprobe dummy_driver
[18167.821725] dummy_driver: GPIO example init
<noinclude>

{{ArticleMainWriter|AlexandreT}}
{{ ArticleApprovedVersion| AlexandreT | ErwanLR (Done), GeraldB (Passed 9Aug'18), BernardP (PASS, 11June'18), FabriceG (PASS, 28June'18) | No previous approved version | PhilipS - 25Sep'18 - 8794 | 5Oct'18 }} 
[[Category:IOs pin management|5]]</noinclude>

==Purpose==

This article gives an example of a driver that '''controls GPIOs from kernel space'''.<br/>

Sample source files are provided as examples: '''kernel module''' (driver), '''device tree''' and '''Makefile'''.<br />

This example is available for [[STM32MP15_Evaluation_boards_-_getting_started | STM32MP15_Evaluation_boards]] or [[STM32MP15_Discovery_kits_-_getting_started | STM32MP15_Discovery_kits]]

==Code==
===Objective===
Sample gpiolib usage code that makes an LED blink for 20 seconds.<br />
<br />


===Device tree===<pre>

dummy_device {
   compatible = "st,dummy";
   status = "okay";
   greenled-gpios = <&gpioa 14 0>;
};</pre>


See [[GPIO_device_tree_configuration]] for more details of GPIO use in a device tree.

===Kernel module code===<syntaxhighlight lang="c"><pre class="brush:c">

#include <linux/module.h>

#include <linux/of_device.h>

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/gpio/consumer.h>

#include <linux/platform_device.h>


struct gpio_desc *red, *green;

static int gpio_init_probe(struct platform_device *pdev)
{
   int i = 0;

   printk("GPIO example init\n");

   /* "greenled" label is matching the device tree declaration. OUT_LOW is the value at init */
   green = devm_gpiod_get(&pdev->dev, "greenled", GPIOD_OUT_LOW);

   /* blink of the green led */	
   while (i < 10)
   {
	ssleep(1);
	gpiod_set_value(green, 1);

	ssleep(1);
	gpiod_set_value(green, 0);

	i++;
   }

   return(0);
}

static int gpio_exit_remove(struct platform_device *pdev)
{
   printk("GPIO example exit\n");

   return(0);
}

/* this structure does the matching with the device tree */
/* if it does not match the compatible field of DT, nothing happens */
static struct of_device_id dummy_match[] = {
    {.compatible = "st,dummy"},
    {/* end node */}
};

static struct platform_driver dummy_driver = {
    .probe = gpio_init_probe,
    .remove = gpio_exit_remove,
    .driver = {
        .name = "dummy_driver",
                .owner = THIS_MODULE,
                .of_match_table = dummy_match,
    }
};

module_platform_driver(dummy_driver);

MODULE_AUTHOR("Bernard Puel");
MODULE_DESCRIPTION("Gpio example");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dummy_driver");</syntaxhighlight></pre>


===Kernel module build===
See [[STM32MP1_Developer_Package#Adding_external_out-of-tree_Linux_kernel_modules|Adding_external_out-of-tree_Linux_kernel_modules]] for further information on module compilation.

{{ReviewsComments|To be updated when the build-method example is added to the ST delivery}}

===Kernel module use===

 {{PC$}} scp dummy_driver.ko root@<board ip address>:/lib/modules/

* Update dependency descriptions for loadable kernel modules, and synchronize the data on disk with memory
 {{Board$}} /sbin/depmod -a
 {{Board$}} sync

* Insert the kernel module example into the Linux kernel
 {{Board$}} modprobe dummy_driver
 [18167.821725] {{Highlight|dummy_driver}}: GPIO example init

<noinclude>

[[Category:IOs pin management|5]]
{{PublicationRequestId | 8794 | 2018-09-25 | PhilipS}}</noinclude>
Line 1: Line 1:
<noinclude>
 
{{ArticleMainWriter|AlexandreT}}
 
{{ ArticleApprovedVersion| AlexandreT | ErwanLR (Done), GeraldB (Passed 9Aug'18), BernardP (PASS, 11June'18), FabriceG (PASS, 28June'18) | No previous approved version | PhilipS - 25Sep'18 - 8794 | 5Oct'18 }}
 
[[Category:IOs pin management|5]]
 
</noinclude>
 
 
 
==Purpose==
 
==Purpose==
   
Line 28: Line 22:
   
 
===Kernel module code===
 
===Kernel module code===
<pre class="brush:c">
+
<syntaxhighlight lang="c">
 
#include <linux/module.h>
 
#include <linux/module.h>
 
#include <linux/of_device.h>
 
#include <linux/of_device.h>
Line 92: Line 86:
 
MODULE_LICENSE("GPL");
 
MODULE_LICENSE("GPL");
 
MODULE_ALIAS("platform:dummy_driver");
 
MODULE_ALIAS("platform:dummy_driver");
</pre>
+
</syntaxhighlight>
   
 
===Kernel module build===
 
===Kernel module build===
Line 110: Line 104:
 
  {{Board$}} modprobe dummy_driver
 
  {{Board$}} modprobe dummy_driver
 
  [18167.821725] {{Highlight|dummy_driver}}: GPIO example init
 
  [18167.821725] {{Highlight|dummy_driver}}: GPIO example init
  +
  +
<noinclude>
  +
[[Category:IOs pin management|5]]
  +
{{PublicationRequestId | 8794 | 2018-09-25 | PhilipS}}
  +
</noinclude>