linux中requst_irq函数参数中的中断号问题
坑位:
硬件同事给了我一个bit,告述我说spi-contrler的中断号是89,让我验一下这个spi-controler是否能用。经过三天,读写功能都测试通过了,但中断就是没法进。我是这样蠢干蛮干的:
requst_irq(89,spi_int_hander, IRQ_TRIGER_RISING, NULL, NULL);
后来问了我导师,他说这个函数里的参数不能直接传硬件中断号,得从设备树获取,获取时核心层函数做了映射将中断号数组中对应的索引作为此函数的参数。得此点拨,如醍醐灌顶,令我拨云见日茅塞顿开。
正解:
设备树中:
interrupt-parent = <&intc>; interrupt = <0 57 1>; //共享中断,57+32=89, 触发方式:上升沿。设备树中共享中断要减32,私有中断要减16
驱动代码中:
void spi_controler_init(void) { int id,version; writel(0, SSIENR); writel(10, BAUDR); writel(1, TXFTLR); writel(1, RXFTLR); writel(0x11, IMR); writel(0x4C7, CTRLR0); writel(0x02, CTRLR1); id = readl(IDR); version = readl(SSI_COMP_VERSION); printk("ID= %#x, version= %#x \n", id, version); } int irq; static int rf9808_probe(struct platform_device *dev) { struct device_node *node; node = of_find_compatible_node(NULL,NULL,"sysnopsys,spi-pl"); // spi_base_addr = ioremap(SSI_BASE_ADDR, 0xff); // en_swich_addr = ioremap(0x4001001C, 4); spi_base_addr = of_iomap(node, 0); en_swich_addr = of_iomap(node, 1); irq = of_irq_get(node,0); printk("irq= %d \n", irq); misc_dev = kzalloc(sizeof(*misc_dev), GFP_KERNEL); misc_dev->fops = &miscdev_fops; misc_dev->name = "rf9808-test"; //主设备号恒为10,自动分配次设备号 misc_dev->minor = MISC_DYNAMIC_MINOR; //3.注册misc设备 misc_register(misc_dev); if(request_irq(irq,spiint_irq_handler, 0, "rf9808-test" , misc_dev->this_device) ) { printk(KERN_DEBUG "requst irq failled \n"); } spi_controler_init(); return 0; } static int rf9808_remove(struct platform_device *dev) { iounmap(spi_base_addr); iounmap(en_swich_addr); free_irq(irq,misc_dev->this_device); misc_deregister(misc_dev); kfree(misc_dev); return 0; } struct of_device_id dts_table[] = { {.compatible = "sysnopsys,spi-pl"}, {}, }; struct platform_driver spi_pl = { .probe = rf9808_probe, .remove = rf9808_remove, .driver = { .name = "rf9808_test_driver", .of_match_table = dts_table, }, }; static int __init test_rf9808_init(void) { platform_driver_register(&spi_pl); return 0; } /** * nufront_cap_cleanup - Driver un-registration call */ static void __exit test_rf9808_cleanup(void) { platform_driver_unregister(&spi_pl); } module_init(test_rf9808_init); module_exit(test_rf9808_cleanup); MODULE_AUTHOR("Nufront,Inc."); MODULE_LICENSE("GPL"); MODULE_ALIAS("spi:rf9808");
使用of_irq_get()函数从设备树中取到中断号,然后再request_irq()。