基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)

作者

彭東林

[email protected]

平臺

tiny4412 ADK

Linux-4.4.4

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

簡介

前面我們實現了一種設備樹下中斷的使用方法,下面介紹第二種,這種方式本質上跟前者是一樣的,使用的是platform_bus的接口。

爲了便於比較,還是以底板上面上的四個按鍵爲例分析,其中前兩個按鍵使用第二種方式,後兩個按鍵使用第一種方式。

正文

原理圖可以參考博文:基於tiny4412的Linux內核移植--- 中斷和GPIO學習(1)

下面是設備樹的改動:

 1 diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
 2 index 610202a..2e69c91 100644
 3 --- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
 4 +++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
 5 @@ -16,6 +16,7 @@
 6  #include <dt-bindings/gpio/gpio.h>
 7  #include <dt-bindings/usb4640/usb4640.h>
 8  #include <dt-bindings/pwm/pwm.h>
 9 +#include <dt-bindings/interrupt-controller/irq.h>
10  #include <autoconf.h>
11  
12  / {
13 @@ -136,6 +137,14 @@
14                 };
15         };
16  #endif
17 +
18 +interrupt_another: interrupt_another {
19 +                       compatible = "tiny4412,interrupt_another";
20 +                       interrupt-parent = <&gpx3>;
21 +                       interrupts = <2 IRQ_TYPE_EDGE_FALLING 3 IRQ_TYPE_EDGE_FALLING>;
22 +                       tiny4412,int_gpio0 = <&gpx3 4 GPIO_ACTIVE_HIGH>;
23 +                       tiny4412,int_gpio1 = <&gpx3 5 GPIO_ACTIVE_HIGH>;
24 +               };
25  };
26  
27  &rtc {

 其中,interrupts屬性值的解析需要看中斷控制器gpx3在創建irq_domain時設置的回調函數exynos_eint_irqd_ops的xlate成員。以後我們再分析。而gpio屬性的值的含義則需要看gpio控制器gpx3在創建時設置的of_xlate回調函數of_gpio_simple_xlate,這個以後分析。

下面看驅動:

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

在platform_device進行populate的時候,已經對其irq資源進行了映射,這個以後分析。

驗證

加載驅動:

[root@tiny4412 mnt]# insmod interrupt_another.ko 
[   33.330879] int_demo_probe enter.
[   33.331896] request irq: 103
[   33.332778] request irq: 104
[   33.333412] int_demo_probe: gpio: 240 ---> irq (107)
[   33.334535] int_demo_probe: gpio: 241 ---> irq (108)

依次按鍵,由於沒有加消抖處理,所以依次按鍵可能會觸發多次中斷

[root@tiny4412 mnt]# [ 1244.082303] int_demo_isr_pdev enter, tiny4412,pdev_irq_0 irq: 103
[ 1244.229761] int_demo_isr_pdev enter, tiny4412,pdev_irq_0 irq: 103
[ 1245.129735] int_demo_isr_pdev enter, tiny4412,pdev_irq_1 irq: 104
[ 1245.283928] int_demo_isr_pdev enter, tiny4412,pdev_irq_1 irq: 104
[ 1246.269231] int_demo_isr_gpio enter, tiny4412,int_gpio0 irq: 107
[ 1246.476101] int_demo_isr_gpio enter, tiny4412,int_gpio0 irq: 107
[ 1247.769903] int_demo_isr_gpio enter, tiny4412,int_gpio1 irq: 108
[ 1248.034338] int_demo_isr_gpio enter, tiny4412,int_gpio1 irq: 108
[ 1248.035396] int_demo_isr_gpio enter, tiny4412,int_gpio1 irq: 108
[ 1248.035858] int_demo_isr_gpio enter, tiny4412,int_gpio1 irq: 108
[ 1248.036218] int_demo_isr_gpio enter, tiny4412,int_gpio1 irq: 108

我們再看看系統中斷資源註冊情況

[root@tiny4412 mnt]# cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 36:          0          0          0          0       GIC  89 Edge      mct_comp_irq
 37:      16511       8820       5442        861       GIC  28 Edge      MCT
 42:          0          0          0          0       PMU  44 Edge      s3c2410-rtc alarm
 43:          0          0          0          0       PMU  45 Edge      s3c2410-rtc tick
 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:        811          0          0          0       GIC 102 Edge      ehci_hcd:usb2, ohci_hcd:usb3
 47:        380          0          0          0       GIC  84 Edge      13800000.serial
 51:         72          0          0          0       GIC  93 Edge      13890000.i2c
 57:          1          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:         47          0          0          0       GIC 109 Edge      dw-mci
103: 8 0 0 0 exynos4210_wkup_irq_chip 2 Edge tiny4412,pdev_irq_0 104: 4 0 0 0 exynos4210_wkup_irq_chip 3 Edge tiny4412,pdev_irq_1 105:          6          0          0          0  exynos4210_wkup_irq_chip   1 Edge      mma7660
106:          1          0          0          0  exynos_gpio_irq_chip   2 Edge      12530000.sdhci cd
107: 6 0 0 0 exynos4210_wkup_irq_chip 4 Edge tiny4412,int_gpio0 108: 9 0 0 0 exynos4210_wkup_irq_chip 5 Edge tiny4412,int_gpio1
IPI0:          0          1          1          1  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:        841       1545        682        838  Rescheduling interrupts
IPI3:          1          3          2          3  Function call interrupts
IPI4:          0          1          1          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

 

未完待續...

你可能感兴趣的:(基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3))