天天看點

寫一個控制gpio的驅動

說明:這裡主要是基于Amlogic_S905X平台上實作的,其實gpio的控制都是通用的,使用的都是标準的gpio操作函數,跟平台無關。通過往節點寫入1或者0來拉高拉低gpio來控制led燈的亮滅。

stvs9:/ $ cd sys/devices/led_ctrl.15/                                          
	stvs9:/sys/devices/led_ctrl.15 $ ls -l
	total 0
	lrwxrwxrwx 1 root root    0 2018-09-11 00:00 driver -> ../../bus/platform/drivers/led_ctrl
	-rw-rw-rw- 1 root root 4096 2018-09-11 00:01 gpio_wps
	-rw-rw-rw- 1 root root 4096 2018-09-11 00:01 gpio_zigbee
	-rw-rw-rw- 1 root root 4096 2018-09-11 00:00 gpio_zwave
	-r--r--r-- 1 root root 4096 2018-09-11 00:00 modalias
	drwxr-xr-x 2 root root    0 1970-01-13 09:47 power
	lrwxrwxrwx 1 root root    0 2018-09-11 00:00 subsystem -> ../../bus/platform
	-rw-r--r-- 1 root root 4096 1970-01-13 09:47 uevent
	stvs9:/sys/devices/led_ctrl.15 $ echo 1 > gpio_zigbee //打開led
	stvs9:/sys/devices/led_ctrl.15 $ echo 0 > gpio_zigbee //關閉led                        
	stvs9:/sys/devices/led_ctrl.15 $ echo 1 > gpio_zwave                           
	stvs9:/sys/devices/led_ctrl.15 $ echo 0 > gpio_zwave                           
	stvs9:/sys/devices/led_ctrl.15 $ echo 1 > gpio_wps                             
	stvs9:/sys/devices/led_ctrl.15 $ echo 0 > gpio_wps
	stvs9:/sys/devices/led_ctrl.15 $ cat gpio_zigbee  //檢視led電平  
           

主要代碼如下:

1、dts的配置:

led_ctrl {

            compatible = "amlogic, led_ctrl";
            dev_name = "led_ctrl";
            status = "okay";
            gpio_zigbee = <&gpio GPIOH_8 GPIO_ACTIVE_HIGH>;
            gpio_zwave = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>;
            gpio_wps = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
      };
           

2、 具體驅動代碼如下:

#include <linux/init.h>
	#include <linux/slab.h>
	#include <linux/module.h>
	#include <linux/kernel.h>
	#include <linux/fs.h>
	#include <linux/cdev.h>
	#include <linux/device.h>
	#include <linux/ioctl.h>
	#include <linux/uaccess.h>
	#include <linux/string.h>
	#include <linux/wait.h>
	#include <linux/types.h>
	#include <linux/proc_fs.h>
	#include <linux/of.h>
	#include <linux/of_gpio.h>
	#include <linux/gpio.h>
	#include <linux/delay.h>
	#include <linux/platform_device.h>
	#include <linux/err.h>

	static int gpio_zigbee;
	static int gpio_zwave;
	static int gpio_wps;

	static ssize_t led_ctrl_gpio_zigbee_show(struct device *dev,
				struct device_attribute *attr, char *buf)
	{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_zigbee));
	}

	static ssize_t led_ctrl_gpio_zwave_show(struct device *dev,
				struct device_attribute *attr, char *buf)
	{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_zwave));
	}

	static ssize_t led_ctrl_gpio_wps_show(struct device *dev,
				struct device_attribute *attr, char *buf)
	{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_wps));
	}

	static ssize_t led_ctrl_gpio_zigbee_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size)
	{
	u8 wp;
	u8 ret;
	ret = sscanf(buf, "%x", (int *)&wp);
	if (wp == 0) {
		gpio_set_value(gpio_zigbee, 0);
		pr_err("-czd-: _%s_ :gpio_zigbee off\n", __func__);
	} else if (wp == 1) {
		gpio_set_value(gpio_zigbee, 1);
		pr_err("-czd-: _%s_ :gpio_zigbee on\n", __func__);
	} else
		pr_err("I only support 0 or 1 to ctrl led on or off\n");
	return size;
	}

	static ssize_t led_ctrl_gpio_zwave_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size)
	{
	u8 wp;
	u8 ret;
	ret = sscanf(buf, "%x", (int *)&wp);
	if (wp == 0) {
		gpio_set_value(gpio_zwave, 0);
		pr_err("-czd-: _%s_ :gpio_zwave off\n", __func__);
	} else if (wp == 1) {
		gpio_set_value(gpio_zwave, 1);
		pr_err("-czd-: _%s_ :gpio_zwave on\n", __func__);
	} else
		pr_err("I only support 0 or 1 to ctrl led on or off\n");
	return size;
	}

	static ssize_t led_ctrl_gpio_wps_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size)
	{
	u8 wp;
	u8 ret;
	ret = sscanf(buf, "%x", (int *)&wp);
	if (wp == 0) {
		gpio_set_value(gpio_wps, 0);
		pr_err("-czd-: _%s_ :gpio_wps off\n", __func__);
	} else if (wp == 1) {
		gpio_set_value(gpio_wps, 1);
		pr_err("-czd-: _%s_ :gpio_wps on\n", __func__);
	} else
		pr_err("I only support 0 or 1 to ctrl led on or off\n");
	return size;
	}

	static DEVICE_ATTR(gpio_zigbee, 0664, led_ctrl_gpio_zigbee_show, led_ctrl_gpio_zigbee_store);
	static DEVICE_ATTR(gpio_zwave, 0664, led_ctrl_gpio_zwave_show, led_ctrl_gpio_zwave_store);
	static DEVICE_ATTR(gpio_wps, 0664, led_ctrl_gpio_wps_show, led_ctrl_gpio_wps_store);


	static int led_ctrl_probe(struct platform_device *pdev)
	{

	struct device_node *led_ctrl_node = pdev->dev.of_node;
	enum of_gpio_flags flags;

	pr_err("---[czd]--- Enter %s\n", __func__);

	gpio_zigbee = of_get_named_gpio_flags(led_ctrl_node,
	"gpio_zigbee", 0, &flags);
		pr_err("---[czd]--- gpio_zigbee is %d --\n", gpio_zigbee);
	if (!gpio_is_valid(gpio_zigbee)) {
		pr_err("gpio_zigbee: %d is invalid\n", gpio_zigbee);
		return -ENODEV;
	}
	if (gpio_request(gpio_zigbee, "gpio_zigbee")) {
	pr_err("gpio_zigbee: %d request failed!\n", gpio_zigbee);
		gpio_free(gpio_zigbee);
		return -ENODEV;
	}

	gpio_zwave = of_get_named_gpio_flags(led_ctrl_node,
	"gpio_zwave", 0, &flags);
		pr_err("---[czd]--- gpio_zwave is %d --\n", gpio_zwave);
	if (!gpio_is_valid(gpio_zwave)) {
	pr_err("gpio_zwave: %d is invalid\n", gpio_zwave);
	return -ENODEV;
	}
	if (gpio_request(gpio_zwave, "gpio_zwave")) {
	pr_err("gpio_zwave: %d request failed!\n", gpio_zwave);
		gpio_free(gpio_zwave);
		return -ENODEV;
	}

	gpio_wps = of_get_named_gpio_flags(led_ctrl_node,
	"gpio_wps", 0, &flags);
	pr_err("---[czd]--- gpio_wps is %d --\n", gpio_wps);
	if (!gpio_is_valid(gpio_wps)) {
	pr_err("gpio_wps: %d is invalid\n", gpio_wps);
	return -ENODEV;
	}
	if (gpio_request(gpio_wps, "gpio_wps")) {
	pr_err("gpio_wps: %d request failed!\n", gpio_wps);
		gpio_free(gpio_wps);
		return -ENODEV;
	}

	gpio_direction_output(gpio_zigbee, 0);
	gpio_direction_output(gpio_zwave, 0);
	gpio_direction_output(gpio_wps, 0);

	device_create_file(&pdev->dev, &dev_attr_gpio_zigbee);
	device_create_file(&pdev->dev, &dev_attr_gpio_zwave);
	device_create_file(&pdev->dev, &dev_attr_gpio_wps);

	pr_err("-czd- led_ctrl_probe sucess..\n");

	return 0;
	}

	static struct of_device_id led_ctrl_match_table[] = {
	{ .compatible = "amlogic, led_ctrl",},
	{},
	};

	static int led_ctrl_remove(struct platform_device *pdv)
	{

	pr_err("led_ctrl_remove...\n");

	return 0;
		}

	static struct platform_driver led_ctrl_driver = {

	.driver = {
		.name = "led_ctrl",
		.owner = THIS_MODULE,
		.of_match_table = led_ctrl_match_table,
	},
	.probe = led_ctrl_probe,
	.remove = led_ctrl_remove,
	};

	static int led_ctrl_init(void)
	{
	pr_err("-czd-: led_ctrl_init start...\n");
	platform_driver_register(&led_ctrl_driver);
	return 0;
	}

	static void led_ctrl_exit(void)
	{
	pr_err("led_ctrl_exit ...\n");
	platform_driver_unregister(&led_ctrl_driver);

	}

	module_init(led_ctrl_init);
	module_exit(led_ctrl_exit);

	MODULE_AUTHOR("caizd");
	MODULE_DESCRIPTION("Device_create Driver");
	MODULE_LICENSE("GPL");

           

繼續閱讀