设备树
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)
{
{
//jimmy
static 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");