下面以按键中断为例看看基于设备数的中断的用法:
设备树:
tq2440_key { compatible = "tq2440,key"; interrupt-parent = <&gpf>; interrupts = <0 IRQ_TYPE_EDGE_FALLING>, <1 IRQ_TYPE_EDGE_FALLING>; key_3 = <&gpf 2 GPIO_ACTIVE_HIGH>; key_4 = <&gpf 4 GPIO_ACTIVE_HIGH>; key_8 = <&gpg 0 GPIO_ACTIVE_HIGH>; };
驱动:
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/platform_device.h> 4 #include <linux/gpio.h> 5 #include <linux/of.h> 6 #include <linux/of_gpio.h> 7 #include <linux/interrupt.h> 8 9 static irqreturn_t tq2440_key_isr(int irq, void *dev_id) 10 { 11 printk("%s enter, irq: %d, %s\n", __func__, irq, (char *)dev_id); 12 return IRQ_HANDLED; 13 } 14 15 static int tq2440_key_probe(struct platform_device *pdev) { 16 struct device *dev = &pdev->dev; 17 int irq_gpio = -1; 18 int irq = -1; 19 20 printk("%s enter.\n", __func__); 21 22 if (!dev->of_node) { 23 dev_err(dev, "no platform data.\n"); 24 return -EINVAL; 25 } 26 27 irq = platform_get_irq(pdev, 0); 28 printk("%s: get irq %d\n", __func__, irq); 29 devm_request_any_context_irq(dev, irq, 30 tq2440_key_isr, IRQF_TRIGGER_FALLING, "key-1", "key-1"); 31 32 irq = platform_get_irq(pdev, 1); 33 printk("%s: get irq %d\n", __func__, irq); 34 devm_request_any_context_irq(dev, irq, 35 tq2440_key_isr, IRQF_TRIGGER_FALLING, "key-2", "key-2"); 36 37 irq_gpio = of_get_named_gpio(dev->of_node, "key_3", 0); 38 irq = gpio_to_irq(irq_gpio); 39 printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq); 40 devm_request_any_context_irq(dev, irq, 41 tq2440_key_isr, IRQF_TRIGGER_FALLING, "key-3", "key-3"); 42 43 irq_gpio = of_get_named_gpio(dev->of_node, "key_4", 0); 44 irq = gpio_to_irq(irq_gpio); 45 printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq); 46 devm_request_any_context_irq(dev, irq, 47 tq2440_key_isr, IRQF_TRIGGER_FALLING, "key-4", "key-4"); 48 49 irq_gpio = of_get_named_gpio(dev->of_node, "key_8", 0); 50 irq = gpio_to_irq(irq_gpio); 51 printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq); 52 devm_request_any_context_irq(dev, irq, 53 tq2440_key_isr, IRQF_TRIGGER_FALLING, "key-8", "key-8"); 54 55 return 0; 56 } 57 58 static int tq2440_key_remove(struct platform_device *pdev) { 59 60 printk("%s enter.\n", __func__); 61 62 return 0; 63 } 64 65 static const struct of_device_id tq2440_key_dt_ids[] = { 66 { .compatible = "tq2440,key", }, 67 {}, 68 }; 69 70 MODULE_DEVICE_TABLE(of, tq2440_key_dt_ids); 71 72 static struct platform_driver tq2440_key_driver = { 73 .driver = { 74 .name = "tq2440_key", 75 .of_match_table = of_match_ptr(tq2440_key_dt_ids), 76 }, 77 .probe = tq2440_key_probe, 78 .remove = tq2440_key_remove, 79 }; 80 81 static int __init tq2440_key_init(void) 82 { 83 int ret; 84 85 ret = platform_driver_register(&tq2440_key_driver); 86 if (ret) 87 printk(KERN_ERR "tq2440_key: probe failed: %d\n", ret); 88 89 return ret; 90 } 91 module_init(tq2440_key_init); 92 93 static void __exit tq2440_key_exit(void) 94 { 95 platform_driver_unregister(&tq2440_key_driver); 96 } 97 module_exit(tq2440_key_exit); 98 99 MODULE_LICENSE("GPL");
启动后,加载驱动,可以看看/proc/interrupts:
[root@tq2440 mnt]# cat /proc/interrupts CPU0 7: 252 s3c-eint 7 Edge eth0 8: 0 s3c 8 Edge s3c2410-rtc tick 13: 37624 s3c 13 Edge samsung_time_irq 15: 7 s3c2410-eint0_3 0 Edge key-1 17: 10 s3c2410-eint0_3 1 Edge key-2 18: 12 s3c2410-eint0_3 2 Edge key-3 19: 6 s3c-eint 4 Edge key-4 20: 0 s3c-eint 0 Edge key-8 26: 0 s3c 26 Edge ohci_hcd:usb1 27: 4 s3c 27 Edge 54000000.i2c 30: 0 s3c 30 Edge s3c2410-rtc alarm 32: 236 s3c-level 32 Level 50000000.serial 33: 2820 s3c-level 33 Level 50000000.serial 59: 0 s3c-level 59 Edge 53000000.watchdog
下面是加载驱动的时候时的log:
<7>[ 29.155953] tq2440_key_probe enter. <7>[ 29.156100] tq2440_key_probe: get irq 15 <7>[ 29.156350] tq2440_key_probe: get irq 17 <7>[ 29.156546] tq2440_key_probe: gpio: 86 ---> irq (18) <7>[ 29.156803] tq2440_key_probe: gpio: 88 ---> irq (19) <7>[ 29.157061] tq2440_key_probe: gpio: 92 ---> irq (20)
按键的时候会看到下面的log:
<7>[ 350.161506] tq2440_key_isr enter, irq: 17, key-2 <7>[ 354.624168] tq2440_key_isr enter, irq: 18, key-3 <7>[ 355.301634] tq2440_key_isr enter, irq: 19, key-4 <7>[ 357.053889] tq2440_key_isr enter, irq: 15, key-1 <7>[ 368.231196] tq2440_key_isr enter, irq: 20, key-8
可以在中断处理函数中将调用栈打印出来:
EINT0_3中断对应的log:
<7>[ 483.595441] [<bf008044>] (tq2440_key_isr [interrupts_demo]) from [<c00447d8>] (__handle_irq_event_percpu+0x3c/0x130) <7>[ 483.595481] [<c00447d8>] (__handle_irq_event_percpu) from [<c00448e8>] (handle_irq_event_percpu+0x1c/0x54) <7>[ 483.595521] [<c00448e8>] (handle_irq_event_percpu) from [<c0044948>] (handle_irq_event+0x28/0x3c) <7>[ 483.595558] [<c0044948>] (handle_irq_event) from [<c00476a8>] (handle_edge_irq+0xbc/0x190) <7>[ 483.595586] [<c00476a8>] (handle_edge_irq) from [<c0043fd8>] (generic_handle_irq+0x2c/0x40) <7>[ 483.595621] [<c0043fd8>] (generic_handle_irq) from [<c00441ac>] (__handle_domain_irq+0x6c/0xcc) <7>[ 483.595653] [<c00441ac>] (__handle_domain_irq) from [<c0009444>] (s3c24xx_handle_irq+0x6c/0x12c) <7>[ 483.595681] [<c0009444>] (s3c24xx_handle_irq) from [<c000e5fc>] (__irq_svc+0x5c/0x78)
EINT4:
<7>[ 594.735684] [<bf008044>] (tq2440_key_isr [interrupts_demo]) from [<c00447d8>] (__handle_irq_event_percpu+0x3c/0x130) <7>[ 594.735725] [<c00447d8>] (__handle_irq_event_percpu) from [<c00448e8>] (handle_irq_event_percpu+0x1c/0x54) <7>[ 594.735764] [<c00448e8>] (handle_irq_event_percpu) from [<c0044948>] (handle_irq_event+0x28/0x3c) <7>[ 594.735801] [<c0044948>] (handle_irq_event) from [<c00476a8>] (handle_edge_irq+0xbc/0x190) <7>[ 594.735832] [<c00476a8>] (handle_edge_irq) from [<c0043fd8>] (generic_handle_irq+0x2c/0x40) <7>[ 594.735878] [<c0043fd8>] (generic_handle_irq) from [<c02490f4>] (s3c24xx_demux_eint4_7+0xa4/0x120) <7>[ 594.735916] [<c02490f4>] (s3c24xx_demux_eint4_7) from [<c00441ac>] (__handle_domain_irq+0x6c/0xcc) <7>[ 594.735946] [<c00441ac>] (__handle_domain_irq) from [<c0009444>] (s3c24xx_handle_irq+0x6c/0x12c) <7>[ 594.735975] [<c0009444>] (s3c24xx_handle_irq) from [<c000e5fc>] (__irq_svc+0x5c/0x78)
EINT8:
<7>[ 652.506024] [<bf008044>] (tq2440_key_isr [interrupts_demo]) from [<c00447d8>] (__handle_irq_event_percpu+0x3c/0x130) <7>[ 652.506065] [<c00447d8>] (__handle_irq_event_percpu) from [<c00448e8>] (handle_irq_event_percpu+0x1c/0x54) <7>[ 652.506106] [<c00448e8>] (handle_irq_event_percpu) from [<c0044948>] (handle_irq_event+0x28/0x3c) <7>[ 652.506142] [<c0044948>] (handle_irq_event) from [<c00476a8>] (handle_edge_irq+0xbc/0x190) <7>[ 652.506171] [<c00476a8>] (handle_edge_irq) from [<c0043fd8>] (generic_handle_irq+0x2c/0x40) <7>[ 652.506219] [<c0043fd8>] (generic_handle_irq) from [<c0249224>] (s3c24xx_demux_eint8_23+0xb4/0x130) <7>[ 652.506258] [<c0249224>] (s3c24xx_demux_eint8_23) from [<c00441ac>] (__handle_domain_irq+0x6c/0xcc) <7>[ 652.506287] [<c00441ac>] (__handle_domain_irq) from [<c0009444>] (s3c24xx_handle_irq+0x6c/0x12c) <7>[ 652.506316] [<c0009444>] (s3c24xx_handle_irq) from [<c000e5fc>] (__irq_svc+0x5c/0x78)
完。