下面的這個驅動文件at91_keyled.c在Atmel提供的linux-at91-linux4sam_5.3下實現了按鍵控制LED的亮滅過程,通過這個簡單的驅動描述了基於DTS的驅動開發模型以及Linux內核裡的GPIO相關的操作函數。
1 /********************************************************************************* 2 * Copyright: (C) 2016 Guo Wenxue<[email protected]> 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 <[email protected]> 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 <[email protected]>"); 163 MODULE_DESCRIPTION("AT91 Linux DTS GPIO driver for Key and LED"); 164 MODULE_LICENSE("GPL"); 165 MODULE_ALIAS("platform:key-leds");
http://xxxxxx/Linuxjc/1138600.html TechArticle