GPIO驱动实例代码
设备树
gpio1: gpio@fec20000 {compatible = "rockchip,gpio-bank";reg = <0x0 0xfec20000 0x0 0x100>;interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;gpio-controller;#gpio-cells = <2>;gpio-ranges = <&pinctrl 0 32 32>;interrupt-controller;#interrupt-cells = <2>;};
gpio-int {compatible = "gpio-int-demo";interrupt-gpio = <&gpio1 RK_PC6 IRQ_TYPE_EDGE_RISING>;status = "okay";};
MAKEFILE
obj-y += gpio-int-demo.o
驱动
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/cpumask.h>struct gpio_int_data {int irq_num;int gpio;
};static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{{//jimmystatic ktime_t start = 0;ktime_t end = 0;s64 duration_us = 0;static u32 counter = 0;static u32 delay_counter = 0;static u32 print_counter = 0;//printk("gpio_keys_gpio_isr: irq %d\n", irq);if (irq == 135){end = ktime_get();if (start == 0){start = ktime_get();}else{duration_us = ktime_to_us(ktime_sub(end, start));start = end;counter++;if (duration_us > 135){delay_counter++; }{if (print_counter > 5000){printk("gpio_soft usec_diff = %lld [%d/%d] virq %d\n", duration_us, delay_counter, counter, irq);print_counter = 0;}else{print_counter++;}}}}}// 可以在这里添加去抖、状态读取等逻辑return IRQ_HANDLED;
}static int gpio_int_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct gpio_int_data *data;enum of_gpio_flags flags;int ret;struct cpumask mask;printk("gpio_int_probe ok\n");data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);if (!data)return -ENOMEM;/* 获取GPIO和中断标志 */data->gpio = of_get_named_gpio_flags(dev->of_node, "interrupt-gpio", 0, &flags);if (!gpio_is_valid(data->gpio)) {dev_err(dev, "Invalid GPIO\n");return -EINVAL;}data->irq_num = gpio_to_irq(data->gpio);/* 请求GPIO */ret = devm_gpio_request_one(dev, data->gpio, GPIOF_IN, "gpio_int");if (ret) {dev_err(dev, "Failed to request GPIO %d\n", data->gpio);return ret;}/* 请求中断 */ret = devm_request_irq(dev, data->irq_num, gpio_irq_handler, flags, dev_name(dev), NULL);if (ret) {dev_err(dev, "Failed to request IRQ %d\n", data->irq_num);return ret;}printk("GPIO %d (IRQ %d) registered successfully.\n", data->gpio, data->irq_num);platform_set_drvdata(pdev, data);return 0;
}static int gpio_int_remove(struct platform_device *pdev)
{pr_info("GPIO interrupt driver removed.\n");return 0;
}static const struct of_device_id gpio_int_of_match[] = {{ .compatible = "gpio-int-demo" },{}
};
MODULE_DEVICE_TABLE(of, gpio_int_of_match);static struct platform_driver gpio_int_driver = {.probe = gpio_int_probe,.remove = gpio_int_remove,.driver = {.name = "gpio-int-demo",.of_match_table = gpio_int_of_match,},
};module_platform_driver(gpio_int_driver);MODULE_AUTHOR("Jimmy.V");
MODULE_DESCRIPTION("GPIO Interrupt Demo Driver for RK3588");
MODULE_LICENSE("GPL v2");