坑位:
硬件同事給了我一個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()。