#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/ide.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include "chrdev_led.h"
#include "imx6ull_led.h"
static int imx6ull_led_probe(struct platform_device *pdev)
{
int ret;
struct imx6ull_led_info *led_info;
if(!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
//申请内存用于存放LED设备的资源
led_info = devm_kzalloc(&pdev->dev, sizeof(struct imx6ull_led_info), GFP_KERNEL);
if(!led_info) {
dev_err(&pdev->dev, "Failed to allocate memory for imx6ull led platform driver\n");
return -ENOMEM;
}
//将LED设备信息绑定到平台设备
platform_set_drvdata(pdev, led_info);
//获取节点信息(不对引脚进行初始化)
led_info->desc = devm_gpiod_get(&pdev->dev, "led", GPIOD_ASIS);
if(IS_ERR(led_info->desc)) {
dev_err(&pdev->dev, "Failed to get GPIO pin for led\n");
return PTR_ERR(led_info->desc);
}
ret = of_property_read_u32(pdev->dev.of_node, "id", &led_info->id);
if(ret)
return ret;
//往内核注册一个LED字符设备
return led_chrdev_register(&led_info->led_cdev, led_info->id, 1, "imx6ull led");
}
static int imx6ull_led_remove(struct platform_device *pdev)
{
struct imx6ull_led_info *led_info = platform_get_drvdata(pdev);
return led_chrdev_unregister(&led_info->led_cdev, led_info->id, 1, "imx6ull led");
}
static const struct of_device_id imx6ull_led_of_match[] = {
{ .compatible = "imx6ull-led" },
{}
};
static struct platform_driver imx6ull_led_driver = {
.probe = imx6ull_led_probe,
.remove = imx6ull_led_remove,
.driver = {
.name = "imx6ull-led",
.of_match_table = imx6ull_led_of_match,
},
};
//------------------------------------------------------
static struct led_drv_func func_list;
static int imx6ull_init_led_gpio(struct cdev *led_cdev, void **private)
{
int ret;
struct imx6ull_led_info *led_info = container_of(led_cdev, struct imx6ull_led_info, led_cdev);
//初始化引脚(无效逻辑值)
ret = gpiod_direction_output(led_info->desc, 0);
if(ret)
return ret;
*private = led_info;
return 0;
}
static int imx6ull_set_led_gpio(void *private, char valid)
{
struct imx6ull_led_info *led_info = (struct imx6ull_led_info *)private;
gpiod_set_value(led_info->desc, (int)valid);
return 0;
}
static int imx6ull_close_led_gpio(void *private)
{
struct imx6ull_led_info *led_info = (struct imx6ull_led_info *)private;
gpiod_set_value(led_info->desc, 0);
return 0;
}
static int __init led_platform_driver_init(void)
{
func_list.func_init_led_gpio = imx6ull_init_led_gpio;
func_list.func_set_led_gpio = imx6ull_set_led_gpio;
func_list.func_close_led_gpio = imx6ull_close_led_gpio;
led_chrdev_register_func(&func_list);
return platform_driver_register(&imx6ull_led_driver);
}
static void __exit led_platform_driver_exit(void)
{
func_list.func_init_led_gpio = NULL;
func_list.func_set_led_gpio = NULL;
func_list.func_close_led_gpio = NULL;
led_chrdev_unregister_func();
platform_driver_unregister(&imx6ull_led_driver);
}
module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);
//-------------------------------------------------------
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David.Tang");