Linux-platform驱动控制led

设备树

led {
	compatible = "gpio-leds";
	label = "green";
	led-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
	status = "okay";
};

驱动

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>




#define PLATFORMLED_NAME "platformled"
#define PLATFORMLED_CNT 1
#define LEDOFF 0 
#define LEDON  1

/* platform_led 设备结构体 */
struct platformled_dev
{
    dev_t devid;            /* 设备号 */
    int major;              /* 主设备号 */
    struct cdev cdev;       /* 字符设备 */
    struct class *class;    /* 类 */
    struct device *device;  /* 设备 */
    struct device_node *node; /* 设备节点 */
    int led0;               /* LED 灯 GPIO 标号 */
};
/* 定义设备结构体变量 */
struct platformled_dev platformled;

/* open 函数 */
static int gpioled_open(struct inode *inode, struct file *filp)
{
    filp->private_data = &platformled; /* 设置私有数据 */
    return 0;
}

/* write 函数 */
static ssize_t gpioled_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    //struct platformled_dev *dev = (struct platformled_dev *)filp->private_data;
    int ret;
    unsigned char databuf[1];

    ret = copy_from_user(databuf, buf, cnt);
    if (ret < 0)
    {
        printk("kernel write failed!\r\n");
        return -EFAULT;
    }
    if (databuf[0] == LEDON)
    {
        gpio_set_value(platformled.led0, 0);
    }
    else if (databuf[0] == LEDOFF)
    {
        gpio_set_value(platformled.led0, 1);
    }
    return 0;
}

/* 字符设备操作集合 */
static struct file_operations platformled_fops = {
    .owner = THIS_MODULE,
    .open = gpioled_open,
    .write = gpioled_write,
};

//匹配设备结构体
static const struct of_device_id led_of_match_table[] = {
    {.compatible = "gpio-leds"},
};

static int platformled_probe(struct platform_device *dev)
{   
	printk("led driver and device was matched!\r\n");
    /* 1、设置设备号 */
    if (platformled.major) {
        platformled.devid = MKDEV(platformled.major, 0);
        register_chrdev_region(platformled.devid, PLATFORMLED_CNT, PLATFORMLED_NAME);
    } else {
        alloc_chrdev_region(&platformled.devid, 0, PLATFORMLED_CNT, PLATFORMLED_NAME);
        platformled.major = MAJOR(platformled.devid);
    }

    /* 2、注册设备 */
    cdev_init(&platformled.cdev, &platformled_fops);
    cdev_add(&platformled.cdev, platformled.devid, PLATFORMLED_CNT);

    /* 3、创建类 */
    platformled.class = class_create(THIS_MODULE, PLATFORMLED_NAME);
    if (IS_ERR(platformled.class)) {
        return PTR_ERR(platformled.class);
    }

    /* 4、创建设备 */
    platformled.device = device_create(platformled.class, NULL, platformled.devid, NULL, PLATFORMLED_NAME);
    if (IS_ERR(platformled.device)) {
        return PTR_ERR(platformled.device);
    }

    /* 5、初始化 IO */ 
    platformled.node = of_find_node_by_path("/led");
    if (platformled.node == NULL){
        printk("gpioled node nost find!\r\n");
        return -EINVAL;
    }

    platformled.led0 = of_get_named_gpio(platformled.node, "led-gpios", 0);
    if (platformled.led0 < 0) {
        printk("can't get led-gpio\r\n");
        return -EINVAL;
    }

    gpio_request(platformled.led0, "led0");
    gpio_direction_output(platformled.led0, 1); /*设置为输出,默认高电平 */
    
    return 0;
}

static int platformled_remove(struct platform_device *dev)
{
	/* 注销设备的时候关闭 LED 灯 */
	gpio_set_value(platformled.led0, 1);
    /* 删除 cdev */
    cdev_del(&platformled.cdev); 
    /* 删除 cdev */
    unregister_chrdev_region(platformled.devid, PLATFORMLED_CNT);
    /* 删除 cdev */
    device_destroy(platformled.class, platformled.devid);
    /* 删除 cdev */
    class_destroy(platformled.class);
	return 0;
}

/* platform 驱动结构体 */
static struct platform_driver platform_driver_led = {
    .driver = {
        .name = "platform_driver_led",//驱动名字
        .of_match_table = led_of_match_table,//设备树匹配表
    },
    .probe = platformled_probe,
    .remove = platformled_remove,
};

/* 入口函数 */
static int __init platformled_init(void)
{
    /* 注册平台级设备驱动 */
    return platform_driver_register(&platform_driver_led);
}

/* 出口函数 */
static void __exit platformled_exit(void)
{
    /* 卸载平台级设备驱动 */
	platform_driver_unregister(&platform_driver_led);
}

module_init(platformled_init);
module_exit(platformled_exit);
MODULE_AUTHOR("chen");
MODULE_LICENSE("GPL");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Paper_Love

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值