修改linux/kernel/arch/arm64/boot/dts/rockchip文件夹下rk3399.dtsi文件,在根节点下添加你的设备。注意compatble属性的值,用于和驱动文件中的compatible匹配。
gpio_cst{
status = "okay";
compatible = "gpio_cst";
firefly-gpio = <&gpio_0 12 GPIO_ACTIVE_HIGH>; /* GPIO_B4 */
}
在drivers文件夹下添加自己的驱动文件夹gpio_cst,并修改本目录下的Makefile文件、Kconfig文件和上级目录中的Makefile文件。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEV_NAME "gpio"
struct gpiopin_dev
{
struct cdev dev;
dev_t dev_id;
struct class *dev_class;
struct device_node *nd;
int gpio;
};
struct gpiopin_dev gpio;
static int gpio_open(struct inode *inode, struct file *pfile)
{
int ret = 0;
pfile->private_data = &gpio;
return ret;
}
static ssize_t gpio_read(struct file *pfile, char __user *buf, size_t size, loff_t *offset)
{
int ret = 0;
struct gpiopin_dev *p;
char level = 0;
p = pfile->private_data;
level = gpio_get_value(p->gpio);
ret = copy_to_user(buf, &level, sizeof(level));
return ret;
}
static ssize_t gpio_write(struct file *pfile, const char __user *buf, size_t size, loff_t *offset)
{
int ret = 0;
struct gpiopin_dev *p;
char level = 0;
p = pfile->private_data;
ret = copy_from_user(&level, buf, size);
gpio_set_value(p->gpio, level);
return ret;
}
static int gpio_release(struct inode * inode , struct file * pfile)
{
return 0;
}
static struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.open = gpio_open,
.read = gpio_read,
.write = gpio_write,
.release = gpio_release,
};
static int gpio_probe(struct platform_device *pdev)
{
struct device *dev;
int ret = -1;
dev_t id = 0;
gpio.nd = of_find_node_by_path("/gpio_cst");
gpio.nd = pdev->dev.of_node;
if(gpio.nd == NULL)
{
printk("***************gpio_cst get node failed*****************\n");
return -1;
}
printk("*****************gpio_cst get node successfully******************\n");
gpio.gpio = of_get_named_gpio(gpio.nd, "firefly-gpio", 0);
if(gpio.gpio < 0)
{
printk("*****************gpio_cst get gpio failed**************\n");
return -1;
}
printk("*****************gpio_cst get gpio successfully*****************\n");
ret = gpio_request(gpio.gpio, "firefly-gpio"); /* 申请GPIO */
if(ret < 0)
{
printk("*************gpio_cst gpio request failed*************\n");
return ret;
}
printk("************gpio_cst gpio request successfully**************\n");
ret = gpio_direction_output(gpio.gpio, 0); /* output,low default */
if(ret<0)
{
printk("*******************gpio_cst gpio set failed*************\n");
gpio_free(gpio.gpio);
return ret;
}
printk("*************gpio_cst gpio set successfully********************\n");
ret = alloc_chrdev_region(&id, 0, 1, DEV_NAME);
if (ret)
{
printk("*************gpio_cst alloc dev-id failed.******************\n");
return ret;
}
printk("***************gpio_cst alloc dev-id successfully.*************\n");
gpio.dev_id = id;
cdev_init(&gpio.dev, &gpio_fops);
ret = cdev_add(&gpio.dev, gpio.dev_id, 1);
if (ret)
{
unregister_chrdev_region(gpio.dev_id, 1);
printk("***************gpio_cst cdev add failed.*************\n");
return ret;
}
gpio.dev_class = class_create(THIS_MODULE, "gpio_class");
if (IS_ERR(gpio.dev_class))
{
printk("***************gpio_cst class_create failed.******************\n");
cdev_del(&gpio.dev);
ret = -EIO;
return ret;
}
printk("***************gpio_cst class_create successfully.***************\n");
dev = device_create(gpio.dev_class, NULL, gpio.dev_id, NULL, DEV_NAME);
if (IS_ERR(dev))
{
return PTR_ERR(dev);
}
return 0;
}
static int gpio_remove(struct platform_device *pdev)
{
gpio_free(gpio.gpio);
device_destroy(gpio.dev_class, gpio.dev_id);
class_destroy(gpio.dev_class);
cdev_del(&gpio.dev);
unregister_chrdev_region(gpio.dev_id, 1);
return 0;
}
static struct of_device_id of_gpio_ids[] = {
{.compatible = "gpio_cst"},
{ }
};
static struct platform_driver gpio_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DEV_NAME,
.of_match_table = of_match_ptr(of_gpio_ids),
},
.probe = gpio_probe,
.remove = gpio_remove,
};
module_platform_driver(gpio_driver);
MODULE_LICENSE("GPL");
kernel目录下make menuconfig
选择Device Drivers,再找到自己写的驱动名称,按空格键使得名称前面为[*],Save产生.config文件,再一路退出。
./build.sh kernel (实习的环境用这条命令,自己搞的话在kernel同级目录下make。编译全部的话,用./build.sh all)
sudo ./rkflash.sh boot
别忘了开发板要进入maskroom模式,以及双usb头线连接。
查看设备树或驱动:
ls /sys/firmware/devicetree/base
ls /proc/device-tree
ls /proc/devices
ls /sys/bus/platform/drivers
ls /sys/bus/platform/devices
1.编写测试程序时 ./rkflash.sh boot别忘了开发板要进入maskroom模式,以及双usb头线连接
2.官方测试方法:sudo cat /sys/kernel/debug/gpio
交叉编译生成可执行文件。
运行可执行文件,查看结果。