基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)
2016-12-25 23:27
337 查看
作者
彭東林pengdonglin137@163.com
平臺
tiny4412 ADKLinux-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
未完待續...
相关文章推荐
- 基於tiny4412的Linux內核移植 --- 实例学习中断背后的知识(1)
- 基於tiny4412的Linux內核移植 --- 实例学习中断背后的知识(2)
- 【TINY4412】LINUX移植笔记:(5)Rootfs文件系统
- 【TINY4412】LINUX移植笔记:(12)NFS网络文件系统
- 基于tiny4412的Linux内核移植 -- PWM子系统学习(七)
- 【TINY4412】LINUX移植笔记:(6)eMMC驱动
- 【TINY4412】LINUX移植笔记:(13)SD卡驱动
- 基于tiny4412的Linux内核移植 -- DM9621NP网卡驱动移植(四)
- 【TINY4412】LINUX移植笔记:(7)LED驱动分析
- 【TINY4412】LINUX移植笔记:(15)SD卡启动Linux内核
- 基于tiny4412的Linux内核移植 -- 设备树的展开
- 【TINY4412】LINUX移植笔记:(8)PWM蜂鸣器
- 【TINY4412】LINUX移植笔记:(16)eMMC启动Linux内核
- 【TINY4412】LINUX移植笔记:(22)设备树LCD按键驱动
- 基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)
- 【TINY4412】LINUX移植笔记:(9)USB驱动
- 【TINY4412】LINUX移植笔记:(17)设备树HELLO WORLD驱动
- 【TINY4412】LINUX移植笔记:(23)设备树LCD触摸屏驱动
- 【TINY4412】QT5移植笔记:(2)QT5.7移植到Linux