你的位置:首页 > 操作系统

[操作系统]at91 linux 4.1.0下dts驱动编程模型


下面的这个驱动文件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");