at91 linux 4.1.0下dts驱动编程模型,at914.1.0
下面的这个驱动文件at91_keyled.c在Atmel提供的linux-at91-linux4sam_5.3下实现了按键控制LED的亮灭过程,通过这个简单的驱动描述了基于DTS的驱动开发模型以及Linux内核里的GPIO相关的操作函数。
1 /*********************************************************************************
2 * Copyright: (C) 2016 Guo Wenxue<guowenxue@gmail.com>
3 * All rights reserved.
4 *
5 * Filename: at91_keyled.c
6 * Description: This is a sample driver for GPIO operation with DTS linux on at91,
7 * which willl turn led on when a button pressed.
8 *
9 * Version: 1.0.0(2016-6-29~)
10 * Author: Guo Wenxue <guowenxue@gmail.com>
11 * ChangeLog: 1, Release initial version on "Wed Jun 29 12:00:44 CST 2016"
12 *
13 *
14 * DTS Changes:
15 * add keyleds support in arch/arm/boot/dts/at91sam9x5cm.dtsi
16 *
17 * keyleds{
18 * compatible = "key-leds";
19 * gpios = <&pioB 18 GPIO_ACTIVE_LOW priv->pin_key=of_get_gpio(pdev->dev.of_node, 0);
20 * &pioB 16 GPIO_ACTIVE_LOW>; priv->pin_key=of_get_gpio(pdev->dev.of_node, 1);
21 * status = "okay";
22 * }
23 *
24 * 1wire_cm {
25 * ... ...
26 * ... ...
27 * }
28 *
29 ********************************************************************************/
30
31 #include <linux/module.h>
32 #include <linux/moduleparam.h>
33 #include <linux/platform_device.h>
34
35 #include <linux/of.h>
36 #include <linux/of_device.h>
37 #include <linux/of_gpio.h>
38 #include <linux/delay.h>
39 #include <linux/gpio.h>
40 #include <linux/interrupt.h>
41
42 typedef struct keyled_priv_s
43 {
44 int pin_key;
45 int pin_led;
46 int led_status;
47 } keyled_priv_t; /*--- end of struct keyled_priv_s ---*/
48
49
50 static const struct of_device_id of_key_leds_match[] = {
51 { .compatible = "key-leds", },
52 {},
53 };
54 MODULE_DEVICE_TABLE(of, of_key_leds_match);
55
56
57 static irqreturn_t key_detect_interrupt(int irq, void *dev_id)
58 {
59 keyled_priv_t *priv = (keyled_priv_t *)dev_id;
60
61 priv->led_status ^= 1;
62 gpio_set_value(priv->pin_led, priv->led_status);
63
64 return IRQ_HANDLED;
65 }
66
67
68 static int at91_keyled_probe(struct platform_device *pdev)
69 {
70 int res;
71 keyled_priv_t *priv;
72
73 printk(KERN_INFO "at91_keyled driver probe\n");
74
75 if( 2 != of_gpio_count(pdev->dev.of_node) )
76 {
77 printk(KERN_ERR "keyled pins definition in dts invalid\n");
78 return -EINVAL;
79 }
80
81 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
82 if(!priv)
83 return -ENOMEM;
84
85 platform_set_drvdata(pdev, priv);
86
87 priv->pin_key=of_get_gpio(pdev->dev.of_node, 0);
88 priv->pin_led=of_get_gpio(pdev->dev.of_node, 1);
89
90 if( gpio_is_valid(priv->pin_key) )
91 {
92 if( (res=devm_gpio_request(&pdev->dev, priv->pin_key, "keyled_key")) < 0 )
93 {
94 dev_err(&pdev->dev, "can't request key gpio %d\n", priv->pin_key);
95 return res;
96 }
97 dev_info(&pdev->dev, "request key gpio %d ok\n", priv->pin_key);
98
99 if( (res=gpio_direction_input(priv->pin_key)) < 0 )
100 {
101 dev_err(&pdev->dev, "can't request input direction key gpio %d\n", priv->pin_key);
102 return res;
103 }
104 dev_info(&pdev->dev, "request input direction key gpio %d ok\n", priv->pin_key);
105
106 printk(KERN_INFO "Key gpio current status: %d\n", gpio_get_value(priv->pin_key));
107
108 res = request_irq( gpio_to_irq(priv->pin_key), key_detect_interrupt, IRQF_TRIGGER_FALLING, "keyled", priv);
109 if( res )
110 {
111 dev_err(&pdev->dev, "can't request IRQ<%d> for key gpio %d\n", gpio_to_irq(priv->pin_key), priv->pin_key);
112 return -EBUSY;
113 }
114 dev_info(&pdev->dev, "request IRQ<%d> for key gpio %d ok\n", gpio_to_irq(priv->pin_key), priv->pin_key);
115 }
116
117 if( gpio_is_valid(priv->pin_led) )
118 {
119 if( (res=devm_gpio_request(&pdev->dev, priv->pin_led, "keyled_led")) < 0 )
120 {
121 dev_err(&pdev->dev, "can't request key gpio %d\n", priv->pin_led);
122 return res;
123 }
124
125 if( (res=gpio_direction_output(priv->pin_led, 0)) < 0 )
126 {
127 dev_err(&pdev->dev, "can't request output direction key gpio %d\n", priv->pin_led);
128 return res;
129 }
130 }
131
132 return 0;
133 }
134
135 static int at91_keyled_remove(struct platform_device *pdev)
136 {
137 keyled_priv_t *priv = platform_get_drvdata(pdev);
138
139 printk(KERN_INFO "at91_keyled driver remove\n");
140
141 devm_gpio_free(&pdev->dev, priv->pin_led);
142 devm_gpio_free(&pdev->dev, priv->pin_key);
143
144 free_irq(gpio_to_irq(priv->pin_key), priv);
145
146 devm_kfree(&pdev->dev, priv);
147
148 return 0;
149 }
150
151 static struct platform_driver at91_keyled_driver = {
152 .probe = at91_keyled_probe,
153 .remove = at91_keyled_remove,
154 .driver = {
155 .name = "key-leds",
156 .of_match_table = of_key_leds_match,
157 },
158 };
159
160 module_platform_driver(at91_keyled_driver);
161
162 MODULE_AUTHOR("guowenxue <guowenxue@gmail.com>");
163 MODULE_DESCRIPTION("AT91 Linux DTS GPIO driver for Key and LED");
164 MODULE_LICENSE("GPL");
165 MODULE_ALIAS("platform:key-leds");