09 GPIO driver
GPIO in Linux system is controlled by the Kernel GPIO subsystem.
GPIO APIs
Include <linux/gpio.h> for control GPIO in linux driver.
gpio_is_valid
To check if a GPIO is valid.
bool gpio_is_valid(int gpio_number);
gpio_number: GPIO that you are planning to useReturn: false if it is not valid otherwise, it returns true.
gpio_request
Request the GPIO
int gpio_request(unsigned gpio, const char *label);
gpio: GPIO that you are planning to uselabel: label used by the kernel for the GPIO in sysfs. You can provide any string that can be seen in/sys/kernel/debug/gpio. Docat /sys/kernel/debug/gpio. You can see the GPIO assigned to the particular GPIO.Return: 0 if success and a negative number if failure.
Request one GPIO
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
Request multiple GPIOs
int gpio_request_array(struct gpio *array, size_t num);
gpio_export
For debugging purposes, you can export the GPIO which is allocated to the sysfs
int gpio_export(unsigned int gpio, bool direction_may_change);
gpio: GPIO that you want to exportdirection_may_change: This parameter controls whether user space is allowed to change the direction of the GPIO- true – Can change
- false – Can’t change.
Return: zero on success, else an error.
When you export a GPIO for example gpio72 with the option direction_may_change true, you can see it in /sys/class/gpio/gpio72/direction.
Once you export the GPIO, you can see the GPIO in /sys/class/gpio/*. There you can the GPIO’s value.
gpio_unexport
Unexport the exported GPIO
void gpio_unexport(unsigned int gpio);
gpio: GPIO that you want to unexport
Set the direction of the GPIO
Set the GPIO direction (output or input)
int gpio_direction_input(unsigned gpio);
int gpio_direction_output(unsigned gpio, int value);
gpio: GPIO that you want to set the direction.value: The value of the GPIO once the output direction is effective.Return: zero on success, else an error.
Set and get value of the GPIO
Once you set the GPIO direction as an output, use this API can set the value of GPIO
void gpio_set_value(unsigned gpio, int value);
gpio: GPIO that you want to change the value.value: value to set to the GPIO.0 – Low,1 – High.
Once you set the GPIO direction as an input, use this API can get the value of GPIO
int gpio_get_value(unsigned gpio);
gpio: GPIO that you want to get the value.Return: GPIO value.0 – Low,1 – High.
GPIO Interrupt (IRQ)
To use interrupt in general, we need to know the IRQ line, and IRQ line is hardware-dependent. Use this API to get the IRQ line for GPIO number
int gpio_to_irq(unsigned gpio);
gpio: GPIO number you want to use with interrupt input.Return: IRQ line
Beside flags for use with normal interrupt, GPIO interrupt also has some flags:
IRQF_TRIGGER_NONEIRQF_TRIGGER_RISINGIRQF_TRIGGER_FALLINGIRQF_TRIGGER_HIGHIRQF_TRIGGER_LOW
gpio_free
Once you have done with the GPIO, then you can release the GPIO which you have allocated previously
void gpio_free(unsigned int gpio);
gpio: GPIO number you want release.
Release multiple GPIOs.
void gpio_free_array(struct gpio *array, size_t num);
Our code
The code located in folder 09_gpio_driver
# To build ko driver
make build-09
# To clean ko driver
make clean-09
# To upload ko driver to our board
make upload-09
[root@luckfox root]# ls
dfc.ko fo.ko gd.ko ioctrl.ko mam.ko ofd.ko pf.ko sys_fs.ko user_app wq.ko
[root@luckfox root]# insmod gd.ko
[root@luckfox root]# ls /dev/ | grep gd
gd_dev
[root@luckfox root]# cat /dev/g
gd_dev gpiochip0 gpiochip1 gpiochip2 gpiochip3 gpiochip4
[root@luckfox root]# cat /dev/gd_dev
1
[root@luckfox root]# echo 0 > /dev/gd_dev
[root@luckfox root]# cat /dev/gd_dev
0
[root@luckfox root]# dmesg | tail
[ 230.852866] GPIO_irqNumber = 68
[ 230.852913] gd module inserted successfully.
[ 246.923002] gd File Read
[ 246.923035] GPIO_OUTPUT state: 1
[ 246.923764] gd File Read
[ 255.918031] gd File Write
[ 255.918063] gd File Write
[ 264.001442] gd File Read
[ 264.001476] GPIO_OUTPUT state: 0
[ 264.002215] gd File Read
[root@luckfox root]# dmesg | tail
[ 246.923035] GPIO_OUTPUT state: 1
[ 246.923764] gd File Read
[ 255.918031] gd File Write
[ 255.918063] gd File Write
[ 264.001442] gd File Read
[ 264.001476] GPIO_OUTPUT state: 0
[ 264.002215] gd File Read
[ 275.075895] Interrupt Occurred : GPIO_72_IN
[ 275.464539] Interrupt Occurred : GPIO_72_IN
[ 275.808131] Interrupt Occurred : GPIO_72_IN
[root@luckfox root]#