一,设备树下的platform

在设备树引入后,platform结构中的 platform_device 就可以用设备树去代替了。设备树下的 platform驱动相较于原始的 platform驱动,还需要把platform_device中描述的设备信息放到设备树中,同时修改paltform_drvier中对资源的读取方法即可。

二,在设备树中描述设备信息

使用 platform_device 时,我们可以通过name字段或者id_table来匹配或设备和驱动,当platform_device变成设备树时,则使用of_match_table方法来匹配。of_match_table对于设备树来说,要做的事,就是保证设备节点的compatible属性和platform_driver中的 compatible 保持一致。

alinxled
{compatible = "alinx-led";pinctrl-names = "default";pinctrl-0 = <&pinctrl_led_default>;alinxled-gpios = <&gpio0 0 0>;
};

of_match_table:

paltform_drvier 中的 compatible 属性设置,compatible 位于paltform_drvier->device_driver->of_device_id->compatible,保证和设备树中的 compatible 字段一致即可。of_device_id结构体在paltform_drvier结构体中的成员名为 of_match_table,of 匹配表。 初始化示例如下:

static const struct of_device_id led_of_match[] =
{/* compatible 字段和设备树中保持一致 */{ .compatible = "alinx-led" },{/* Sentinel */}
};

pinctrl 子系统和gpio 子系统下的设备树,写法都是一样的,直接用 就行了。叧要注意设备节点中的compatible属性,要和platform_driver 中的compatible保持一致。

amba
{……slcr@f8000000 {pinctrl@700 {pinctrl_led_default: led-default {mux {groups = "gpio0_0_grp";function = "gpio0";};conf {pins = "MIO0";io-standard = <1>;bias-disable;slew-rate = <0>;};};};};
};alinxled
{compatible = "alinx-led";pinctrl-names = "default";pinctrl-0 = <&pinctrl_led_default>;alinxled-gpios = <&gpio0 0 0>;
};

三,驱动程序

#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 DEVICE_NAME       "gpio_leds"
/* 设备号个数 */
#define DEVID_COUNT       1
/* 驱动个数 */
#define DRIVE_COUNT       1
/* 主设备号 */
#define MAJOR_AX
/* 次设备号 */
#define MINOR_AX          0
/* LED点亮时输入的值 */
#define ALINX_LED_ON      1
/* LED熄灭时输入的值 */
#define ALINX_LED_OFF     0/* 把驱动代码中会用到的数据打包进设备结构体 */
struct alinx_char_dev{dev_t              devid;       //设备号struct cdev        cdev;        //字符设备struct class       *class;      //类struct device      *device;     //设备struct device_node *nd;         //设备树的设备节点int                ax_led_gpio; //gpio号
};
/* 声明设备结构体 */
static struct alinx_char_dev alinx_char = {.cdev = {.owner = THIS_MODULE,},
};/* open函数实现, 对应到Linux系统调用函数的open函数 */
static int gpio_leds_open(struct inode *inode_p, struct file *file_p)
{  /* 设置私有数据 */file_p->private_data = &alinx_char;    return 0;
}  /* write函数实现, 对应到Linux系统调用函数的write函数 */
static ssize_t gpio_leds_write(struct file *file_p, const char __user *buf, size_t len, loff_t *loff_t_p)
{  int retvalue;unsigned char databuf[1];  /* 获取私有数据 */struct alinx_char_dev *dev = file_p->private_data;/* 获取用户数据 */retvalue = copy_from_user(databuf, buf, len);  if(retvalue < 0) {printk("alinx led write failed\r\n");return -EFAULT;} if(databuf[0] == ALINX_LED_ON){/* gpio_set_value方法设置GPIO的值, 使用!!对0或者1二值化 */gpio_set_value(dev->ax_led_gpio, !!1);}else if(databuf[0] == ALINX_LED_OFF){gpio_set_value(dev->ax_led_gpio, !!0);}else{printk("gpio_test para err\n");}return 0;
}  /* release函数实现, 对应到Linux系统调用函数的close函数 */
static int gpio_leds_release(struct inode *inode_p, struct file *file_p)
{   return 0;
}  /* file_operations结构体声明, 是上面open、write实现函数与系统调用函数对应的关键 */
static struct file_operations ax_char_fops = {  .owner   = THIS_MODULE,  .open    = gpio_leds_open,  .write   = gpio_leds_write,     .release = gpio_leds_release,
};/* probe函数实现, 驱动和设备匹配时会被调用 */
static int gpio_leds_probe(struct platform_device *dev)
{    /* 用于接受返回值 */u32 ret = 0;/* 获取设备节点 */alinx_char.nd = of_find_node_by_path("/alinxled");if(alinx_char.nd == NULL)    {printk("gpioled node nost find\r\n");return -EINVAL;}/* 获取节点中gpio标号 */alinx_char.ax_led_gpio = of_get_named_gpio(alinx_char.nd, "alinxled-gpios", 0);if(alinx_char.ax_led_gpio < 0)    {printk("can not get alinxled-gpios\r\n");return -EINVAL;}/* 申请gpio标号对应的引脚 */ret = gpio_request(alinx_char.ax_led_gpio, "alinxled");if(ret != 0){printk("can not request gpio\r\n");}/* 把这个io设置为输出 */ret = gpio_direction_output(alinx_char.ax_led_gpio, 1);if(ret < 0){printk("can not set gpio\r\n");}/* 注册设备号 */alloc_chrdev_region(&alinx_char.devid, MINOR_AX, DEVID_COUNT, DEVICE_NAME);/* 初始化字符设备结构体 */cdev_init(&alinx_char.cdev, &ax_char_fops);/* 注册字符设备 */cdev_add(&alinx_char.cdev, alinx_char.devid, DRIVE_COUNT);/* 创建类 */alinx_char.class = class_create(THIS_MODULE, DEVICE_NAME);if(IS_ERR(alinx_char.class)) {return PTR_ERR(alinx_char.class);}/* 创建设备节点 */alinx_char.device = device_create(alinx_char.class, NULL, alinx_char.devid, NULL, DEVICE_NAME);if (IS_ERR(alinx_char.device)) {return PTR_ERR(alinx_char.device);}return 0;
}static int gpio_leds_remove(struct platform_device *dev)
{/* 注销字符设备 */cdev_del(&alinx_char.cdev);/* 注销设备号 */unregister_chrdev_region(alinx_char.devid, DEVID_COUNT);/* 删除设备节点 */device_destroy(alinx_char.class, alinx_char.devid);/* 删除类 */class_destroy(alinx_char.class);return 0;
}/* 初始化of_match_table */
static const struct of_device_id led_of_match[] = {/* compatible字段和设备树中保持一致 */{ .compatible = "alinx-led" },{/* Sentinel */}
};/* 声明并初始化platform驱动 */
static struct platform_driver led_driver = {.driver = {/* name字段需要保留 */.name = "alinx-led",/* 用of_match_table代替name匹配 */.of_match_table = led_of_match,},.probe  = gpio_leds_probe,.remove = gpio_leds_remove,
};/* 驱动入口函数 */
static int __init gpio_led_drv_init(void)
{/* 在入口函数中调用platform_driver_register, 注册platform驱动 */return platform_driver_register(&led_driver);
}/* 驱动出口函数 */
static void __exit gpio_led_dev_exit(void)
{/* 在出口函数中调用platform_driver_register, 卸载platform驱动 */platform_driver_unregister(&led_driver);
}/* 标记加载、卸载函数 */
module_init(gpio_led_drv_init);
module_exit(gpio_led_dev_exit);/* 驱动描述信息 */
MODULE_AUTHOR("Alinx");
MODULE_ALIAS("gpio_led");
MODULE_DESCRIPTION("PLATFORM DT LED driver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL"); 

四,应用

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>int main(int argc, char **argv)
{int fd;char buf;/* 验证输入参数个数 */if(3 != argc){printf("none para\n");return -1;}/* 打开输入的设备文件, 获取文件句柄 */fd = open(argv[1], O_RDWR);if(fd < 0){/* 打开文件失败 */printf("Can't open file %s\r\n", argv[1]);return -1;}/* 判断输入参数, on就点亮led, off则熄灭led */if(!strcmp("on",argv[2])){printf("ps_led1 on\n");buf = 1;write(fd, &buf, 1);}else if(!strcmp("off",argv[2])){printf("ps_led1 off\n");buf = 0;write(fd, &buf, 1);}else{/* 输入参数错误 */printf("wrong para\n");return -2;}/* 操作结束后关闭文件 */close(fd);return 0;
}

platform与设备树相关推荐

  1. platform和设备树驱动蜂鸣器

    目录 1.plat_fom介绍: 2.设备树介绍: 3.实现过程: 1.设备树:(以exynos-fs4412为例) 2.平台驱动: 3.驱动的启动函数: 4.驱动卸载 1.platform介绍: 从 ...

  2. 设备树下的platform 驱动编写

    目录 设备树下的platform 驱动简介 硬件原理图分析 实验程序编写 修改设备树文件 platform 驱动程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 上一章我们详细的 ...

  3. 3.X内核下设备树–platform设备驱动

    1.历史的车轮总是向前,技术更替.在linus 同学发出那句 WFK 后内核进入了设备树时代(站在驱动工程师角度). 前几天我已经被mach-imx 中的文件折磨的夜不能眠.我终于在一个清晨,喝完一杯 ...

  4. Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用

    关与设备树的概念,我们在Exynos4412 内核移植(六)-- 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用 Device Tree是一种描述硬件的数据结构,设备树源(De ...

  5. 驱动程序开发:无设备树和有设备树的platform驱动

    1.Linux 驱动的分离与分层   对与对IO进行最简单的读写操作,无需考虑太多的怎么使它重用性强,而像I2C. SPI.LCD 等这些复杂外设的驱动,Linux 系统要考虑到驱动的可重用性,因此提 ...

  6. 设备树下的 platform 驱动开发框架

    1. 设备树下的platform驱动开发 platform驱动框架分为总线.设备和驱动,其中总线是由Linux内核提供,在编写驱动时只要关注于设备和驱动的具体实现即可.Linux下的platform驱 ...

  7. Linux 设备树下的 platform 驱动实验基于正点原子IMX6ULL开发板

    1 设备树下的 platform 驱动简介 platform 驱动框架分为总线.设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是 Linux 内核提供的,我们在编写驱动的时候只要关注于设备和 ...

  8. Linux 设备树下的 platform 驱动示例

    1.简介 基于总线.设备和驱动这样的驱动框架,Linux 内核提出来 platform 这个虚拟总线,相应的也有 platform 设备和 platform 驱动. Linux 总线设备和驱动模式 2 ...

  9. 设备树下的platform驱动编写

    文章目录 一.设备树下的platform驱动简介 1.在设备树中创建设备节点 2.编写 platform 驱动的时候要注意兼容属性 3.编写platform驱动 二.硬件原理图分析 三.实验程序编写 ...

最新文章

  1. 利用多个域名来存储网站资源
  2. 数据结构和算法之时间复杂度
  3. “睡服”面试官系列第五篇之proxy(建议收藏学习)
  4. 东软 软件工程1 软件危机 软件工程 软件生命周期
  5. 分类和目标检测的性能评价指标【转载】
  6. CactiEZ的使用
  7. urllib、requests库整理
  8. 派生类对基类成员的访问控制之公有继承
  9. Fabric环境配置
  10. Advertising on Instagram 如何在Instagram上发布广告 Lynda课程中文字幕
  11. 制作产品原型时要注意什么?
  12. 如何做公司网站设计,有哪些步骤?
  13. linux终端设备:pty设备初始化、创建过程
  14. QT 调用 百度翻译API 写的在线翻译程序
  15. sql 处理数据字段为空 如果为空转换成别的值
  16. 2019 南昌网络赛D FFT多个多项式相乘
  17. 遥感技术在城市监测中的作用有哪些?
  18. 计算机技术与软件(初级、中级、高级)考试(软考)是什么?软考的时间安排是什么时候?
  19. 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记
  20. iOS适配iPhoneX/iphone11/iphone12 导航栏高度 (刘海屏幕)

热门文章

  1. 向着第二层 第一阶段第二十四天
  2. vue使用addrouter添加动态路由
  3. Redis之Codis
  4. Python爬虫教程-Python爬取股票数据过程详解
  5. 如何有效发电子邮件简历
  6. 为什么电脑邮箱收不到邮件,怎么回事?
  7. 游戏引擎与游戏引擎开发入门
  8. 视频压缩 ffmpeg
  9. 蓝松短视频----更新日志(一直更新中...)
  10. 深度篇——目标检测史(八) 细说 CornerNet-Lite 目标检测