我有一个GPIO外围设备,在Device中定义为:
gpio0: gpio@2300000
{
compatible = "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};我想为此编写一个中断处理程序(作为内核模块)。但是这个IRQ号码(66)是一个硬件号码,我需要一个虚拟的Linux号才能把它传递给request_irq。
我怎么能得到这个号码?,只有一个中断控制器。
有没有办法做到这一点,而无需编写平台设备驱动程序(因为可能已经有一个在系统中工作,我想我不能注册另一个)。
发布于 2018-08-03 09:33:09
根据您的注释,您希望将GPIO注册为中断。您发布的设备树的节点是中断控制器节点,这与我们手头的任务无关。
要将gpio注册为中断,首先需要找到可以配置为中断的GPIO (在大多数现代处理器中,所有GPIO都支持中断),然后必须通过多路复用来确保它不被其他设备使用(如果SPI或UART等人使用它,则可以从设备树中禁用它们,如果您不使用该实体)。
现在您可以使用一个GPIO引脚了。在内核上找到与之对应的GPIO号(这取决于处理器及其承载板的体系结构)。
当你有了它,你可以只写一个简单的模块,它将导出你的GPIO并使用它作为中断。
下面是http://derekmolloy.ie的一个片段
gpio_request(gpioButton, "sysfs"); // Set up the gpioButton
gpio_direction_input(gpioButton); // Set the button GPIO to be an input
gpio_set_debounce(gpioButton, 200); // Debounce the button with a delay of 200ms
gpio_export(gpioButton, false); // Causes gpio115 to appear in /sys/class/gpio
// the bool argument prevents the direction from being changed
// Perform a quick test to see that the button is working as expected on LKM load
printk(KERN_INFO "GPIO_TEST: The button state is currently: %d\n", gpio_get_value(gpioButton));
// GPIO numbers and IRQ numbers are not the same! This function performs the mapping for us
irqNumber = gpio_to_irq(gpioButton);
printk(KERN_INFO "GPIO_TEST: The button is mapped to IRQ: %d\n", irqNumber);
// This next call requests an interrupt line
result = request_irq(irqNumber, // The interrupt number requested
(irq_handler_t) ebbgpio_irq_handler, // The pointer to the handler function below
IRQF_TRIGGER_RISING, // Interrupt on rising edge (button press, not release)
"ebb_gpio_handler", // Used in /proc/interrupts to identify the owner
NULL); // The *dev_id for shared interrupt lines, NULL is okay链接到完整的代码。
发布于 2022-10-11 09:31:33
对于那些不试图创建GPIO驱动程序但仍然需要从HW获得Linux虚拟IRQ的人,平台驱动程序有一个特定的API。您可以注册一个平台驱动程序,然后在探测过程中调用
/**
* platform_get_irq - get an IRQ for a device
* @dev: platform device
* @num: IRQ number index
*
* Gets an IRQ for a platform device and prints an error message if finding the
* IRQ fails. Device drivers should check the return value for errors so as to
* not pass a negative integer value to the request_irq() APIs.
*
* Return: non-zero IRQ number on success, negative error number on failure.
*/
int platform_get_irq(struct platform_device *dev, unsigned int num);详细解释
为了达到你的目标,你有很多不同的选择:
of_irq_get)platform_get_irq)GPIO驱动程序接口
如果您的平台具有可编程的GPIO,则可以使用GPIO驱动程序接口。见@yashC回复。在您的具体情况下,考虑到您的设备是GPIO的一部分,您应该采用这种方法。
低级设备树APIs
如果希望直接与设备树交互,则可以使用此解决方案。Imho,您应该遵循这种方法,只有当您正在编写一个特定的(和非通用的)驱动程序,您需要一个“脏和干净”的方式去做。
static const struct of_device_id qoriq_gpio_match_table[] =
{
{ .compatible = "fsl,qoriq-gpio" },
{ }
};
np = of_find_matching_node(NULL, qoriq_gpio_match_table);
if (!np)
{
pr_err("No device tree node for qoriq-gpio\n");
return -ENODEV;
}
// decode a node's IRQ and return it as a Linux IRQ number
irq_num = of_irq_get(np, 0);
// request_irq(...)设备驱动程序基础设施API
基本上,您必须注册一个platform driver。
static const struct of_device_id qoriq_gpio_match_table[] =
{
{ .compatible = "fsl,qoriq-gpio" },
{ }
};
static struct platform_driver qoriq_gpi_driver = {
.driver = {
.name = "qoriq-gpio",
.of_match_table = qoriq_gpio_match_table
},
.probe = qoriq_gpio_probe
};
static int qoriq_gpio_probe(struct platform_device *pdev)
{
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
// request_irq(...)
}在Kernelv5.19之前,您还可以使用:platform_get_resource(pdev, IORESOURCE_IRQ, 0); API,目前它是再也没有了。
如果你的设备更通用,你应该使用这种方法(例如。您正在使用几个具有不同DTs的板)。
https://stackoverflow.com/questions/51637425
复制相似问题