zoukankan      html  css  js  c++  java
  • 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)

    作者

    彭東林

    pengdonglin137@163.com

    平臺

    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
    ", __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
    ", __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.
    ", __func__);
     42 
     43     if (!dev->of_node) {
     44         dev_err(dev, "no platform data.
    ");
     45         goto err0;
     46     }
     47 
     48     data = devm_kmalloc(dev, sizeof(*data)*4, GFP_KERNEL);
     49     if (!data) {
     50         dev_err(dev, "no memory.
    ");
     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
    ",
     61                 irq, ret);
     62             goto err0;
     63         }
     64         printk("request irq: %d
    ", 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
    ",
     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
    ",
     83                 irq_gpio, irq);
     84             goto err0;
     85         }
     86 
     87         data[i+2].irq = irq;
     88 
     89         printk("%s: gpio: %d ---> irq (%d)
    ", __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
    ",
     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.
    ", __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
    ", 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

    未完待續...

  • 相关阅读:
    HTTP与HTTPS
    各种排序算法的比较
    数据结构之堆排序
    数据结构之希尔排序
    快速排序与归并排序的区别与联系
    数据结构之快速排序
    DVWA-4.3 File Inclusion(文件包含)-High-利用file协议绕过防护策略
    DVWA-4.2 File Inclusion(文件包含)-Medium-双写绕过str_replace替换规则
    DVWA-4.1 File Inclusion(文件包含)-Low
    DVWA-3.4 CSRF(跨站请求伪造)-Impossible
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/6220939.html
Copyright © 2011-2022 走看看