您的位置:首页 > 运维架构 > Linux

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

2016-12-25 23:27 337 查看

作者

彭東林

pengdonglin137@163.com

平臺

tiny4412 ADK

Linux-4.4.4

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

簡介

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

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

正文

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

下面是設備樹的改動:

diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index 610202a..2e69c91 100644
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -16,6 +16,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/usb4640/usb4640.h>
#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/interrupt-controller/irq.h>
#include <autoconf.h>

/ {
@@ -136,6 +137,14 @@
};
};
#endif
+
+interrupt_another: interrupt_another {
+                       compatible = "tiny4412,interrupt_another";
+                       interrupt-parent = <&gpx3>;
+                       interrupts = <2 IRQ_TYPE_EDGE_FALLING 3 IRQ_TYPE_EDGE_FALLING>;
+                       tiny4412,int_gpio0 = <&gpx3 4 GPIO_ACTIVE_HIGH>;
+                       tiny4412,int_gpio1 = <&gpx3 5 GPIO_ACTIVE_HIGH>;
+               };
};

&rtc {


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

下面看驅動:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>

typedef struct
{
int gpio;
int irq;
char name[20];
}int_demo_data_t;

static irqreturn_t int_demo_isr_pdev(int irq, void *dev_id)
{
int_demo_data_t *data = dev_id;

printk("%s enter, %s irq: %d\n", __func__, data->name, irq);

return IRQ_HANDLED;
}

static irqreturn_t int_demo_isr_gpio(int irq, void *dev_id)
{
int_demo_data_t *data = dev_id;

printk("%s enter, %s irq: %d\n", __func__, data->name, irq);
return IRQ_HANDLED;
}

static int int_demo_probe(struct platform_device *pdev) {
struct device *dev = &pdev->dev;
int irq_gpio = -1;
int irq = -1;
int ret = 0;
int i = 0;
int_demo_data_t *data = NULL;

printk("%s enter.\n", __func__);

if (!dev->of_node) {
dev_err(dev, "no platform data.\n");
goto err0;
}

data = devm_kmalloc(dev, sizeof(*data)*4, GFP_KERNEL);
if (!data) {
dev_err(dev, "no memory.\n");
goto err0;
}

for (i = 0; i < 2; i++) {
irq = platform_get_irq(pdev, i);
sprintf(data[i].name, "tiny4412,pdev_irq_%d", i);
ret = devm_request_any_context_irq(dev, irq,
int_demo_isr_pdev, IRQF_TRIGGER_FALLING, data[i].name, data+i);
if (ret < 0) {
dev_err(dev, "Unable to claim irq %d; error %d\n",
irq, ret);
goto err0;
}
printk("request irq: %d\n", irq);
}

for (i = 0; i < 2; i++) {
sprintf(data[i+2].name, "tiny4412,int_gpio%d", i);
irq_gpio = of_get_named_gpio(dev->of_node,
data[i+2].name, 0);
if (irq_gpio < 0) {
dev_err(dev, "Looking up %s property in node %s failed %d\n",
data[i].name, dev->of_node->full_name, irq_gpio);
goto err0;
}

data[i+2].gpio = irq_gpio;

irq = gpio_to_irq(irq_gpio);
if (irq < 0) {
dev_err(dev,
"Unable to get irq number for GPIO %d, error %d\n",
irq_gpio, irq);
goto err0;
}

data[i+2].irq = irq;

printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq);

ret = devm_request_any_context_irq(dev, irq,
int_demo_isr_gpio, IRQF_TRIGGER_FALLING, data[i+2].name, data+i+2);
if (ret < 0) {
dev_err(dev, "Unable to claim irq %d; error %d\n",
irq, ret);
goto err0;
}
}

return 0;

err0:
return -EINVAL;
}

static int int_demo_remove(struct platform_device *pdev) {

printk("%s enter.\n", __func__);
return 0;
}

static const struct of_device_id int_demo_dt_ids[] = {
{ .compatible = "tiny4412,interrupt_another", },
{},
};

MODULE_DEVICE_TABLE(of, int_demo_dt_ids);

static struct platform_driver int_demo_driver = {
.driver        = {
.name    = "interrupt_another",
.of_match_table    = of_match_ptr(int_demo_dt_ids),
},
.probe        = int_demo_probe,
.remove        = int_demo_remove,
};

static int __init int_demo_init(void)
{
int ret;

ret = platform_driver_register(&int_demo_driver);
if (ret)
printk(KERN_ERR "int demo: probe failed: %d\n", ret);

return ret;
}
module_init(int_demo_init);

static void __exit int_demo_exit(void)
{
platform_driver_unregister(&int_demo_driver);
}
module_exit(int_demo_exit);

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


未完待續...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: