一个led的platform驱动案例

本案例用于抄作业,直接复制修改就可以快速编写驱动。

当你对驱动非常熟悉的时候,不需要每次都要写,除非对驱动生疏,那么建议自己手动敲代码;写程序就应该是复制粘贴,hahaha…

device部分

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/err.h>

#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>

#include <linux/timer.h>
#include <linux/jiffies.h>

#include <linux/platform_device.h>



#define LED_NAME "nameLED3"
#define CHRDEV_COUNT_MAX 1


struct led_platform_dev_t{
    struct cdev cdev;           //注册设备
    struct class *class;        //类
    struct device *device;      //设备
    dev_t devid;                //设备id
    int major;                  //主设备号
    int minor;                  //次设备号


    struct device_node *nd;
    int led_gpio;


    struct timer_list timer;//定时器
    
};

struct led_platform_dev_t led_platform_dev;



void led_device_release(struct device *dev)
{
 printk("led_device_release\r\n");
}

static struct resource res[2] = {
    [0] = {
        .start = 0x200000001,
        .end = 0x200000005,
        .flags = IORESOURCE_MEM,
    },

     [1] = {
        .start = 0x200000006,
        .end = 0x200000007,
        .flags = IORESOURCE_MEM,
    },
};

static struct platform_device led_platform_device = {
    .name = "platform_led",//-1表示无此设备
    .dev = {
        .release = led_device_release,
    },
    .num_resources = ARRAY_SIZE(res),
    .resource = res,
};


static struct file_operations led_platform_fops={
    .owner = THIS_MODULE,
    // .open = led3_open,
    // .release = led3_release,
    // .write = led3_write,
    // //.read = led3_read,
    // .unlocked_ioctl = led3_ioctl,
};



//驱动入口
static int __init led_platform_init(void)
{
    int ret = 0;

    ret = platform_device_register(&led_platform_device);


    printk("led platform init\r\n");
    return 0;
}

static void __exit led_platform_exit(void)
{
    platform_device_unregister(&led_platform_device);

    printk("led platform exit!\r\n");
}

//注册驱动和卸载
module_init(led_platform_init);
module_exit(led_platform_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("China Shanghai/zhouchenliang");



driver部分

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/err.h>

#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>

#include <linux/timer.h>
#include <linux/jiffies.h>

#include <linux/ide.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>



#define LED_NAME "nameLED3"
#define CHRDEV_COUNT_MAX 1


struct led_platform_dev_t{
    struct cdev cdev;           //注册设备
    struct class *class;        //类
    struct device *device;      //设备
    dev_t devid;                //设备id
    int major;                  //主设备号
    int minor;                  //次设备号


    struct device_node *nd;
    int led_gpio;

    struct timer_list timer;//定时器
};

struct led_platform_dev_t led_platform_dev;



static int led_platform_open(struct inode *inode,struct file *filp)
{
    printk("led_platform_open\r\n");

    filp->private_data = &led_platform_dev;//文件私有数据
    return 0;
}

static int led_platform_release(struct inode *inode,struct file *filp)
{
    printk("led_platform_release\r\n");

    //struct led_platform_dev_t *dev = (struct led_platform_dev_t)filp->private_data;

    return 0;
}

static ssize_t led_platform_write(struct file *filp,const __user char *buf,size_t count, loff_t *ppos)
{
    int ret = 0;

    // ret = copy_from_user(writeBuf,buf,count);
    // if(ret < 0)
    // {
    //     printk("led_write copy_from_user error\r\n");
    //     return -1;
    // }

    printk("led_platform_write\r\n");
    return 0;
}

static struct file_operations led_platform_fops={
    .owner = THIS_MODULE,
    .open = led_platform_open,
    .release = led_platform_release,
    .write = led_platform_write,
    // //.read = led3_read,
    // .unlocked_ioctl = led3_ioctl,
};



static int led_driver_probe(struct platform_device *dev)
{
    // int i=0;
    // struct resource *led_source[2];

    //1.从设备里面获取资源
    // for(i=0;i<2;i++)
    // {
    //     led_source[i] = platform_get_resource(dev,IORESOURCE_MEM,i);
    //     if(led_source[i] == NULL)
    //     {
    //         return -EINVAL;
    //     }
    // }

    //内存映射
    //IMX6U_CCM_CCGR1 = ioremap(ledsource[0]->start,resource_size(led_source[0]));


    int ret = -1;

    /*设备号注册*/
    led_platform_dev.major = 0;//直接系统申请设备号
    if(led_platform_dev.major)//给定主设备号
    {
        led_platform_dev.devid = MKDEV(led_platform_dev.major,0);
        ret = register_chrdev_region(led_platform_dev.devid,CHRDEV_COUNT_MAX,LED_NAME);
    }
    else//没有给定主设备号
    {
        ret = alloc_chrdev_region(&led_platform_dev.devid,0,CHRDEV_COUNT_MAX,LED_NAME);//自动申请设备号
        led_platform_dev.major = MAJOR(led_platform_dev.devid);
        led_platform_dev.minor = MINOR(led_platform_dev.devid);
    }

    if(ret < 0)
    {
        printk("register_chdev_region faild!\r\n");
        return -EIO;
    }

    /*注册字符设备*/
    led_platform_dev.cdev.owner = THIS_MODULE;
    cdev_init(&led_platform_dev.cdev,&led_platform_fops);//初始化
    ret = cdev_add(&led_platform_dev.cdev,led_platform_dev.devid,CHRDEV_COUNT_MAX);//添加函数
    if(ret < 0)
    {
        printk("cdev_init faild!\r\n");
        cdev_del(&led_platform_dev.cdev);
        unregister_chrdev_region(led_platform_dev.devid,CHRDEV_COUNT_MAX);
        return -EIO;
    }

    /*自动创建设备节点*/
    led_platform_dev.class = class_create(led_platform_fops.owner,LED_NAME);
    if(IS_ERR(led_platform_dev.class))
    {
        cdev_del(&led_platform_dev.cdev);
        unregister_chrdev_region(led_platform_dev.devid,CHRDEV_COUNT_MAX);
        return PTR_ERR(led_platform_dev.class);
    }

    led_platform_dev.device = device_create(led_platform_dev.class,NULL,led_platform_dev.devid,NULL,LED_NAME);
    if(IS_ERR(led_platform_dev.device))
    {
        class_destroy(led_platform_dev.class);
        cdev_del(&led_platform_dev.cdev);
        unregister_chrdev_region(led_platform_dev.devid,CHRDEV_COUNT_MAX);
        return PTR_ERR(led_platform_dev.device);
    }

    //设备树,获取设备节点
#if 0
    led_platform_dev.nd = of_find_node_by_path("/gpioled");
    if(led_platform_dev.nd == NULL)
    {
        printk("of_find_node_by_path faild!\r\n");
        return -EINVAL;
    }
#endif

    led_platform_dev.nd = dev->dev.of_node;

    // //获取LED对应的GPIO
    led_platform_dev.led_gpio = of_get_named_gpio(led_platform_dev.nd,"gpios",0);
    if(led_platform_dev.led_gpio < 0)
    {
        printk("of_get_named_gpio faild!\r\n");
        return -EINVAL;
    }

    // //申请IO
    // ret = gpio_request(led_platform_dev.led_gpio,"gpio_pin_1");
    // if(ret)
    // {
    //     printk("gpio_request faild!\r\n");
    //     return -EINVAL;
    // }

    // //使用IO 设置为输出
    // ret = gpio_direction_output(led_platform_dev.led_gpio,1);
    // if(ret)
    // {
    //     printk("gpio_direction_output faild!\r\n");
    //     return -EINVAL;
    // }

    // //输出低电平 ,点亮led灯
    // gpio_set_value(led_platform_dev.led_gpio,1);
    
    printk("led_driver_probe\r\n");
    return 0;
}

static int led_driver_remove(struct platform_device *dev)
{
    //关闭led灯
    // gpio_set_value(led_platform_dev.led_gpio,0);

    /*删除字符设备*/
    cdev_del(&led_platform_dev.cdev);

    /*注销字符设备*/
    unregister_chrdev_region(led_platform_dev.devid,CHRDEV_COUNT_MAX);

    /*删除设备*/
    device_destroy(led_platform_dev.class,led_platform_dev.devid);

    /*删除类*/
    class_destroy(led_platform_dev.class);


    //释放IO
    gpio_free(led_platform_dev.led_gpio);

    printk("led_driver_remove\r\n");
    return 0;
}




static const struct of_device_id led_of_match[] = 
{
    {
        .compatible = "gpio-leds",
        .data = NULL
    },
    {
        /*Sentinel*/
    },
};

static struct platform_driver led_platform_driver = {
    .driver = {
        //.name = "sunxi-init-gpio",//无设备树的时候,用于名字匹配
        .of_match_table = of_match_ptr(led_of_match),//设备树匹配表
    },
    .probe = led_driver_probe,
    .remove = led_driver_remove,
    
};


//驱动入口
static int __init led_platform_init(void)
{
    int ret = 0;

    //注册platform驱动
    ret = platform_driver_register(&led_platform_driver);
    if(ret){
		pr_err("led_platform_init user platform_driver_register  fail\n");
		return -1;
	}

    printk("led_platform_init\r\n");
    return ret;
}

static void __exit led_platform_exit(void)
{

    platform_driver_unregister(&led_platform_driver);


    printk("led_platform_exit\r\n");
}

//注册驱动和卸载
module_init(led_platform_init);
module_exit(led_platform_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("China Shanghai/zhouchenliang");



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值