MTK6737平台的GPIO驱动例程(三)

在原先的设备驱动文件上增加上更加方便的交互方式那就是sysfs接口,使用device_create_file用于在sys下创建设备的属性节点。

注意一下device_attribute可以使用一下两种方法初始化

 

1、使用DEVICE_ATTR初始化结构体device_attribute,下面代码示例:

static DEVICE_ATTR(demo, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo, 0444,demo_show,NULL);
其中参数:mode可以直接定义成只读0444,只写0222,或者读写都行的0666。。 
_show和_store函数当没有的时候用NULL赋值,对函数的名称和内容没有具体要求,甚至可以和别的属性相同。

2、也可以使用直接赋值的方法初始化device_attribute结构体,下面代码示例:

static struct device_attribute dev_attr_demo = {
    .attr = {
        .name = "demo", 
        .mode = (S_IRUGO | S_IWUSR) 
    },
    .show = demo_show,
    .store = demo_store,
};
下面上代码,其实就是增加了这么一个接口操作立马很容易了,你就可以不用写测试程序了。

#include <linux/slab.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <generated/autoconf.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>

#include "mt-plat/mtgpio.h"
#include <linux/types.h>
#include <mt-plat/mt_gpio.h>
#include <mt-plat/mt_gpio_core.h>
#include <mach/gpio_const.h>

#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/seq_file.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/kobject.h>
#include <linux/regulator/consumer.h>


/* 生命函数定义 */
static int mygpio_probe(struct platform_device *pdev);
static int mygpio_remove(struct platform_device *pdev);

static ssize_t my_gpio96_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);

struct pinctrl *pinctrlio96;
struct pinctrl_state *pio96_output0, *pio96_output1;

static const struct of_device_id mygpio_of_match[] = {
    { .compatible = "mykgpio", },
    {},
};

static struct platform_driver mygpio_driver = {
    .remove = mygpio_remove,
    .probe = mygpio_probe,
    .driver = {
            .name = "myGPIO",
            .owner = THIS_MODULE,
            .of_match_table = mygpio_of_match,
    },
};


static struct device_attribute mygpio96_attr = {
    .attr = {
        .name = "mygpio96",
        .mode = 0222,                /*mode可以直接定义成只读0444,只写0222,或者读写都行的0666。*/
    },
    
    .store  = &my_gpio96_store,
};


/* 设置管教的状态  level=1 输出高电平 level=0 输出低电平*/
void my673x_gpio_output(int level)
{
    printk("[myGPIO]my673x_gpio_output level = %d\n", level);
    
    /* 设置名字为"my_state_io96_output0"这个pinctrl对应引脚的pin state */
    if (level==1)
        pinctrl_select_state(pinctrlio96, pio96_output1);
    if (level==0)
        pinctrl_select_state(pinctrlio96, pio96_output0);
}


//属性文件的store方法(也就是写)
static ssize_t my_gpio96_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int temp=0;
        
    sscanf(buf, "%d", &temp);     /*将buf中的值以%d的形式赋值给temp*/
    printk("[myGPIO]my673x_gpio_output level = %d \n", temp);
    
    my673x_gpio_output(temp);
    
    return count;
}

static int mygpio_misc_open(struct inode *inode, struct file *file)
{
    printk("MyGPIO OPen. \r\n");
    
    return 0;
}


static int mygpio_misc_release(struct inode *inode, struct file *file)
{
    printk("MyGPIO Release. \r\n");
    
    return 0;
}

static long mygpio_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    printk("MyGPIO Ioctl. \r\n");
    
    printk("MyGPIO cmd=%d \r\n", cmd);
    
    /* 根据命令执行相应的操作 */
    switch(cmd) {
        /* 输出GPIO96高电平 */
        case 1:
            my673x_gpio_output(1);
            break;
 
        /* 输出GPIO96低电平 */
        case 0:
            my673x_gpio_output(0);
            break;
 
        default:
            return -EINVAL;
    }

    
    return 0;
}

static const struct file_operations mygpio_fops = {
 /* .owner = THIS_MODULE, */
    .open = mygpio_misc_open,
    .release = mygpio_misc_release,
    .unlocked_ioctl = mygpio_unlocked_ioctl,
};


static struct miscdevice mygpio_misc_device = {
    .minor = MISC_DYNAMIC_MINOR,        //动态设备号
    .name = "myGPIO",
    .fops = &mygpio_fops,
};

/* My GPIO probe */
static int mygpio_probe(struct platform_device *pdev)
{
    int ret = 0;
    
    printk("MyGPIO Probe. \r\n");
    
    /* 注册一个misc设备 */
    ret = misc_register(&mygpio_misc_device);
    if (ret != 0 )
        printk("myGPIO: mygpio_device register failed\n");
    
    /* 在/sys/devices/节点下创建名字是“mygpio96”设备节点 */
    /* 所生成的设备节点:/sys/devices/soc/soc:mygpio@10212000 */
    /* echo 0 > mygpio96 灯亮 | echo 1 > mygpio96 灯灭 */
    if (device_create_file(&pdev->dev, &mygpio96_attr))        //关联到哪个设备
        printk("[MyGPIO] Unable to create sysfs entry: '%s'\n", mygpio96_attr.attr.name);


    
    /* 获取pin control state holder 的句柄 */
    pinctrlio96 = devm_pinctrl_get(&pdev->dev);
    if (IS_ERR(pinctrlio96)) {
        ret = PTR_ERR(pinctrlio96);
        printk("fwq Cannot find mygpio pinctrlio96!\n");
        return ret;
    }
    
    /* dts中 pinctrl-names = "my_state_io96_output0", "my_state_io96_output1"; */
    /* 得到设备树中名字为 my_state_io96_output0和 my_state_io96_output1对应的pin state */
    pio96_output0 = pinctrl_lookup_state(pinctrlio96, "my_state_io96_output0");
    if (IS_ERR(pio96_output0)) {
        ret = PTR_ERR(pio96_output0);
        printk("fwq Cannot find touch pinctrl my_state_io96_output0!\n");
        return ret;
    }
    pio96_output1 = pinctrl_lookup_state(pinctrlio96, "my_state_io96_output1");
    if (IS_ERR(pio96_output1)) {
        ret = PTR_ERR(pio96_output1);
        printk("fwq Cannot find touch pinctrl my_state_io96_output1!\n");
        return ret;
    }
    
    return ret;
}


static int mygpio_remove(struct platform_device *pdev)
{
    int err;
    
    printk("MyGPIO remove. \r\n");

    err = misc_deregister(&mygpio_misc_device);
    if (err)
        printk("deregister gpio\n");
    
    return err;
}

static int __init my_gpio_init(void)
{
    int ret = 0;

    printk("Register MyGPIO platform_driver. \r\n");

    ret = platform_driver_register(&mygpio_driver);
    if(ret != 0 )
        printk("unable to register MyGPIO driver.\n");
    
    return ret;
}

/*---------------------------------------------------------------------------*/
static void __exit my_gpio_exit(void)
{
    platform_driver_unregister(&mygpio_driver);
}

subsys_initcall(my_gpio_init);
/*module_init(my_gpio_init);*/
module_exit(my_gpio_exit);

MODULE_AUTHOR("zue");
MODULE_DESCRIPTION("MY General Purpose Driver (GPIO)");
MODULE_LICENSE("GPL v2");
在设备注册后会在/sys/devices/soc/soc:mygpio@10212000目录下生成一个设备节点,其实也可以使用find命令直接搜索你注册设备节点名称。

可以看到连接在96号管脚的LED会随着echo的1或者0灭或者亮。这样测试LED驱动就不用再次写测试程序了。

 
-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值