ZYNQ7000_Linux_EMIO_LED

一、设备树和bit

在设备树中PL下添加一个GPIO,这里使用标号56。

		ch_emio {
			compatible = "ch,emio_led";
			enable_pin { 
				label = "enable";
				gpios = <&gpio0 56 0>;
			};
		};

vivado 工程打开GPIO,并约束好引脚到LED。编译生成新的.bit文件。
在这里插入图片描述

二、程序

/*
 * LEDs driver for GPIOs
 *
 * Copyright (C) 2007 8D Technologies inc.
 * Raphael Assenat <[email protected]>
 * Copyright (C) 2008 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/string.h>  
#include <linux/io.h>

#define DEVICE_NAME "emio_led"

struct gpio_emio{
	char name[10];
	struct gpio_desc *gpiod;
	struct device *gpio_dev;
}gpio_emio_dev;

static int gpio_emio_major;
static struct class* gpio_emio_class = NULL;
static struct device* gpio_emio_device = NULL;

static ssize_t gpio_emio_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
	int ret;
	unsigned char val;

	ret = copy_from_user(&val,buf,1);
	if(ret != 0){
		printk("gpio_emio : copy_from_user ret = %d \n",ret);
		return -1;
		}

	printk("gpio_emio_write : gpio = %d \n",val);
	gpiod_direction_output(gpio_emio_dev.gpiod, val);
	return 0;
}

static const struct file_operations gpio_emio_fops = {
	.owner = THIS_MODULE,
	.write = gpio_emio_write,
};

static int gpio_emio_init(void)
{
	int ret = 0;
	char reset_dev_compatible[40] = "ch,emio_led";
	char lable_name[40] = "enable";
	const char *ledname = lable_name;
	struct device_node *reset_dev_node;
	struct platform_device *reset_pdev;
	struct fwnode_handle *reset_child;

	reset_dev_node = of_find_compatible_node(NULL,NULL,reset_dev_compatible);
	if(reset_dev_node == NULL)
		{
			printk("gpio_emio_init : can't find emio_led \n");
			return -ENODEV;		
		}
	reset_pdev = of_find_device_by_node(reset_dev_node);
	gpio_emio_dev.gpio_dev = &(reset_pdev->dev);
	ret = device_get_child_node_count(gpio_emio_dev.gpio_dev);
	if(!ret)
		{
			printk("gpio_emio_init : gpio device get child node count %d \n",ret);
			return -ENODEV;
		}
	
	reset_child = device_get_next_child_node(gpio_emio_dev.gpio_dev,NULL);
	if(!reset_child)
		{
			printk("gpio_emio_init: device get next child node NULL\n");
			return -ENODEV;
		}

	gpio_emio_dev.gpiod = devm_fwnode_get_gpiod_from_child(gpio_emio_dev.gpio_dev, NULL, reset_child,GPIOD_ASIS,ledname);
	if(IS_ERR(gpio_emio_dev.gpiod))
		{
			printk("gpio_emio_init: devm_get_gpiod_from_child NULL\n");
			return -ENODEV;
		}
	gpiod_direction_output(gpio_emio_dev.gpiod, 1);

	//////////////////////////////////////////////////////////////////////////
	gpio_emio_major = register_chrdev(0,DEVICE_NAME,&gpio_emio_fops);
	if(gpio_emio_major < 0 )
		{
			printk("emio_init:failed to register device.\n");
			return -1;
		}
	gpio_emio_class = class_create(THIS_MODULE ,"gpio_emio_driver");
	if(IS_ERR(gpio_emio_class)){
		printk("emio_init:failed to create gpio_emio module class.\n");
		unregister_chrdev(gpio_emio_major,DEVICE_NAME);
		return -1;
		}
	
	gpio_emio_device = device_create(gpio_emio_class,NULL,MKDEV(gpio_emio_major,0),NULL,"gpio0");
	if(IS_ERR(gpio_emio_device))
		{
			printk("gpio_emio_init: failed to create device \n");
			class_unregister(gpio_emio_class);
			class_destroy(gpio_emio_class);
			unregister_chrdev(gpio_emio_major,DEVICE_NAME);
			return -1;
		}
	printk("gpio_emio init done\n");
	return 0;
}

static void gpio_emio_exit(void)
{
	gpiod_direction_output(gpio_emio_dev.gpiod,0);
	devm_gpiod_put(gpio_emio_dev.gpio_dev,gpio_emio_dev.gpiod);
	device_destroy(gpio_emio_class,MKDEV(gpio_emio_major,0));
	class_unregister(gpio_emio_class);
	class_destroy(gpio_emio_class);
	unregister_chrdev(gpio_emio_major,DEVICE_NAME);

	printk("gpio_emio exit done \n");
}

module_init(gpio_emio_init);
module_exit(gpio_emio_exit);

MODULE_AUTHOR("emio");
MODULE_DESCRIPTION("gpio_emio dirver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("gpio_emio");

三、结果

测试程序同上,改下设备名。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Chi_Hong/article/details/84581017