设备树学习之(一)GPIO中断

转载于:  http://blog.csdn.net/lizuobin2/article/details/54563587

     http://www.cnblogs.com/pengdonglin137/p/6082796.html

tiny4412 ADK

Linux-4.4.4  (4.4.1类似)

u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uImage做了稍許改動

 

在tiny4412的底板上有四個key,如下:

 

上圖中,在沒有按鍵的時候,對應的GPIO是被拉高的,當按下鍵的時候,對應的GPIO被拉低,從而產生一個下降沿中斷。

有了上面的準備,首先我們需要修改設備樹,添加相應的節點和相關的屬性:

 

1 diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
 2 index 610202a..a130047 100644
 3 --- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
 4 +++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
 5 @@ -136,6 +136,14 @@
 6                 };
 7         };
 8  #endif
 9 +
10 +    interrupt_demo: interrupt_demo {
11 +               compatible = "tiny4412,interrupt_demo";
12 +        tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>;
13 +        tiny4412,int_gpio2 = <&gpx3 3 GPIO_ACTIVE_HIGH>;
14 +        tiny4412,int_gpio3 = <&gpx3 4 GPIO_ACTIVE_HIGH>;
15 +        tiny4412,int_gpio4 = <&gpx3 5 GPIO_ACTIVE_HIGH>;
16 +    };
17  };

 

 

 

 上面的代碼中,我們添加了四個屬性,對應的就是那四個key對應的gpio,參考gpx3的實現(exynos4x12-pinctrl.dtsi): 

 

gpx3: gpx3 {
            gpio-controller;
            #gpio-cells = <2>;

            interrupt-controller;
            #interrupt-cells = <2>;
        };

 

 

 

 可以看到,gpx3含有gpio-controllerinterrupt-controller屬性,表示它是一個gpio控制器和中斷控制器,它的gpio-cell爲2,意味着應該給這個gpx3傳遞兩個參數,以

tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>

爲例,這兩個參數就是2GPIO_ACTIVE_HIGH,如果參數不對的話,比如只傳了一個參數2,那麼在調用of_get_named_gpio會出現如下錯誤:

[   31.133799] /interrupt_demo: arguments longer than property
[   31.133935] interrupt_demo interrupt_demo: Looking up tiny4412,int_gpio4 property in node /interrupt_demo failed -22
[   31.144562] interrupt_demo: probe of interrupt_demo failed with error -22

 使用 make dtbs 編譯完設備樹。

在Samsung的pinctrl驅動中加一些log:

 

@@ -622,6 +626,8 @@ static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
        struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
        unsigned int virq;
 
+    printk("%s enter.\n", __func__);
+
        if (!bank->irq_domain)
                return -ENXIO;

 

 

 

 然後我們編寫對應的驅動程序:

 

  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 typedef struct 
 10 {
 11     int gpio;
 12     int irq;
 13     char name[20];
 14 }int_demo_data_t;
 15 
 16 static irqreturn_t int_demo_isr(int irq, void *dev_id)
 17 {
 18     int_demo_data_t *data = dev_id;
 19 
 20     printk("%s enter, %s: gpio:%d, irq: %d\n", __func__, data->name, data->gpio, data->irq);
 21 
 22     return IRQ_HANDLED;
 23 }
 24 
 25 static int int_demo_probe(struct platform_device *pdev) {
 26     struct device *dev = &pdev->dev;
 27     int irq_gpio = -1;
 28     int irq = -1;
 29     int ret = 0;
 30     int i = 0;
 31     int_demo_data_t *data = NULL;
 32 
 33     printk("%s enter.\n", __func__);
 34 
 35     if (!dev->of_node) {
 36         dev_err(dev, "no platform data.\n");
 37         goto err1;
 38     }
 39 
 40     data = devm_kmalloc(dev, sizeof(*data)*4, GFP_KERNEL);
 41     if (!data) {
 42         dev_err(dev, "no memory.\n");
 43         goto err0;
 44     }
 45 
 46 #if 0
 47     for (i = 3; i >= 0; i--) {
 48         sprintf(data[i].name, "tiny4412,int_gpio%d", i+1);
 49 #else
 50     for (i = 0; i < 4; i++) {
 51 #endif
 52         irq_gpio = of_get_named_gpio(dev->of_node,
 53             data[i].name, 0);
 54         if (irq_gpio < 0) {
 55             dev_err(dev, "Looking up %s property in node %s failed %d\n",
 56                 data[i].name, dev->of_node->full_name, irq_gpio);
 57             goto err1;
 58         }
 59 
 60         data[i].gpio = irq_gpio;
 61 
 62         irq = gpio_to_irq(irq_gpio);
 63         if (irq < 0) {
 64             dev_err(dev,
 65                 "Unable to get irq number for GPIO %d, error %d\n",
 66                 irq_gpio, irq);
 67             goto err1;
 68         }
 69         
 70         data[i].irq = irq;
 71 
 72         printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq);
 73 
 74         ret = devm_request_any_context_irq(dev, irq,
 75             int_demo_isr, IRQF_TRIGGER_FALLING, data[i].name, data+i);
 76         if (ret < 0) {
 77             dev_err(dev, "Unable to claim irq %d; error %d\n",
 78                 irq, ret);
 79             goto err1;
 80         }
 81     }
 82  
 83     return 0;
 84 
 85 err1:
 86     devm_kfree(dev, data);
 87 err0:
 88     return -EINVAL;
 89 }
 90 
 91 static int int_demo_remove(struct platform_device *pdev) {
 92 
 93     printk("%s enter.\n", __func__);
 94 
 95     return 0;
 96 }
 97 
 98 static const struct of_device_id int_demo_dt_ids[] = {
 99     { .compatible = "tiny4412,interrupt_demo", },
100     {},
101 };
102 
103 MODULE_DEVICE_TABLE(of, int_demo_dt_ids);
104 
105 static struct platform_driver int_demo_driver = {
106     .driver        = {
107         .name    = "interrupt_demo",
108         .of_match_table    = of_match_ptr(int_demo_dt_ids),
109     },
110     .probe        = int_demo_probe,
111     .remove        = int_demo_remove,
112 };
113 
114 static int __init int_demo_init(void)
115 {
116     int ret;
117 
118     ret = platform_driver_register(&int_demo_driver);
119     if (ret)
120         printk(KERN_ERR "int demo: probe failed: %d\n", ret);
121 
122     return ret;
123 }
124 module_init(int_demo_init);
125 
126 static void __exit int_demo_exit(void)
127 {
128     platform_driver_unregister(&int_demo_driver);
129 }
130 module_exit(int_demo_exit);
131 
132 MODULE_LICENSE("GPL");

  

 編譯驅動後,將ko文件拷貝到nfs目錄下,然後在開發板上執行 mount -t nfs -o nolock 192.168.2.6:/nfsroot /mnt 將共享目錄從PC上掛載到開發板上,然後insmod這個驅動:

 

[root@tiny4412 ]# mount -t nfs -o nolock 192.168.2.6:/nfsroot /mnt
[root@tiny4412 ]# cd /mnt
[root@tiny4412 mnt]# ls
fdt                interrupt_demo.ko  tiny4412.dts
[root@tiny4412 mnt]# insmod interrupt_demo.ko 
[ 1655.872546] int_demo_probe enter.
[ 1655.872841] samsung_gpio_to_irq enter.
[ 1655.873061] int_demo_probe: gpio: 238 ---> irq (105)
[ 1655.873716] samsung_gpio_to_irq enter.
[ 1655.873906] int_demo_probe: gpio: 239 ---> irq (106)
[ 1655.874424] samsung_gpio_to_irq enter.
[ 1655.874773] int_demo_probe: gpio: 240 ---> irq (107)
[ 1655.879981] samsung_gpio_to_irq enter.
[ 1655.883485] int_demo_probe: gpio: 241 ---> irq (108)
[root@tiny4412 mnt]# 
// 然後我們嘗試按底板上的按鍵,會看到相應的中斷log
[root@tiny4412 mnt]# [   33.462207] int_demo_isr enter, tiny4412,int_gpio1: gpio:238, irq: 105
[   33.657304] int_demo_isr enter, tiny4412,int_gpio1: gpio:238, irq: 105
[   35.769955] int_demo_isr enter, tiny4412,int_gpio3: gpio:240, irq: 107
[   35.951373] int_demo_isr enter, tiny4412,int_gpio3: gpio:240, irq: 107
[   36.525804] int_demo_isr enter, tiny4412,int_gpio4: gpio:241, irq: 108
[   36.698501] int_demo_isr enter, tiny4412,int_gpio4: gpio:241, irq: 108
[   41.710481] int_demo_isr enter, tiny4412,int_gpio2: gpio:239, irq: 106
[   41.857190] int_demo_isr enter, tiny4412,int_gpio2: gpio:239, irq: 106

[root@tiny4412 mnt]# cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 36:          0          0          0          0       GIC  89 Edge      mct_comp_irq
 37:       1054        566        579        339       GIC  28 Edge      MCT
 44:         34          0          0          0       GIC 107 Edge      mmc0
 45:          1          0          0          0       GIC 103 Edge      12480000.hsotg, 12480000.hsotg, dwc2_hsotg:usb1
 46:        508          0          0          0       GIC 102 Edge      ehci_hcd:usb2, ohci_hcd:usb3
 47:        197          0          0          0       GIC  84 Edge      13800000.serial
 51:         52          0          0          0       GIC  93 Edge      13890000.i2c
 57:          0          0          0          0       GIC  67 Edge      12680000.pdma
 58:          0          0          0          0       GIC  68 Edge      12690000.pdma
 59:          0          0          0          0       GIC  66 Edge      12850000.mdma
 71:          0          0          0          0       GIC  79 Edge      11400000.pinctrl
 72:          1          0          0          0       GIC  78 Edge      11000000.pinctrl
 90:          0          0          0          0  COMBINER  80 Edge      3860000.pinctrl
 91:          0          0          0          0       GIC 104 Edge      106e0000.pinctrl
 95:         48          0          0          0       GIC 109 Edge      dw-mci
103:          2          0          0          0  exynos4210_wkup_irq_chip   1 Edge      mma7660
104:          1          0          0          0  exynos_gpio_irq_chip   2 Edge      12530000.sdhci cd
105:          2          0          0          0  exynos4210_wkup_irq_chip   2 Edge      tiny4412,int_gpio1
106:          2          0          0          0  exynos4210_wkup_irq_chip   3 Edge      tiny4412,int_gpio2
107:          2          0          0          0  exynos4210_wkup_irq_chip   4 Edge      tiny4412,int_gpio3
108:          2          0          0          0  exynos4210_wkup_irq_chip   5 Edge      tiny4412,int_gpio4
IPI0:          0          1          1          1  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:        852       1809        422        537  Rescheduling interrupts
IPI3:          0          2          2          2  Function call interrupts
IPI4:          0          1          2          1  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  IRQ work interrupts
IPI7:          0          0          0          0  completion interrupts
Err:          0

 

 

 

 如果我們修改驅動驅動,改變一下中斷的申請順序,然後重啓系統(測試發現,如果不重啓系統,而是重新加載新的驅動,gpio跟irq的對應關系沒有發生改變)

 

#if 1
    for (i = 3; i >= 0; i--) {
        sprintf(data[i].name, "tiny4412,int_gpio%d", i+1);
#else
    for (i = 0; i < 4; i++) {
#endif

 此時,會看到如下的log:

 

[root@tiny4412 mnt]# insmod interrupt_demo.ko 
[  119.735726] int_demo_probe enter.
[  119.736295] samsung_gpio_to_irq enter.
[  119.736417] int_demo_probe: gpio: 241 ---> irq (105)
[  119.736852] samsung_gpio_to_irq enter.
[  119.736985] int_demo_probe: gpio: 240 ---> irq (106)
[  119.737254] samsung_gpio_to_irq enter.
[  119.737893] int_demo_probe: gpio: 239 ---> irq (107)
[  119.743029] samsung_gpio_to_irq enter.
[  119.746631] int_demo_probe: gpio: 238 ---> irq (108)
[root@tiny4412 mnt]# cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 36:          0          0          0          0       GIC  89 Edge      mct_comp_irq
 37:       1799        966        883        145       GIC  28 Edge      MCT
... ...
105:          0          0          0          0  exynos4210_wkup_irq_chip   5 Edge      tiny4412,int_gpio4
106:          0          0          0          0  exynos4210_wkup_irq_chip   4 Edge      tiny4412,int_gpio3
107:          0          0          0          0  exynos4210_wkup_irq_chip   3 Edge      tiny4412,int_gpio2
108:          0          0          0          0  exynos4210_wkup_irq_chip   2 Edge      tiny4412,int_gpio1
... ...

 

 

 


 


posted on 2017-03-22 15:02  Red_Point  阅读(992)  评论(0)    收藏  举报

导航