LINUX设备驱动开发之0418

目前Android厂商大都使用kernel+ramdisk.img+dt.img的方式打包成boot.img。


Device Tree的基本语法


DTS文件主要由:root-node、child-node、property、include组成。
root-node:由‘/’表示,DT的Entry Point,所有设备均以子节点的形式处于根节点下。


child-node:node的形式为node-name{};{}中是该node的实际内容,根节点下一般是Platform设备
总线,外设以子节点形式存在与总线类的节点中。如下的示例中,cpus这个节点位于根节点下,代表着
所有cpu,cpu0~x以子节点形式处于cpus下,代表着SoC上所有的cpu。


property: 属性,以key-value的形式表示,位于节点中。


include file: 用于包含其他源文件到dts中,dtsi一般中多个Machine公用的文件(i代表include)
,h文件在dts中一般用于宏定义。




(一)reg property


(二)chosen node


(三)aliases node


(四)memory node
memory@0{
device_type="memory";
reg=<0x00000000 0x20000000>;
};
(五)compatible node
i2c6@50{
compatible = "samsung,xxxx-i2c";
reg=<0x50 0x4000>;
interrupts=<1 0 4 28>;
};


(六)Property


MSM Device Tree的选取


高通平台DTS中有两个非常重要的id,一个是msm-id配置chipset id,该id是开机后
XBL由硬件寄存器中读取的。


另外一个是board-id,该ID用来表示platform和subtype.
platform_id:
◆ bits 31-24 = Platform Subtype ID    
◆ bits 23-16 = Platform Version (Major)    
◆ bits 15-8  = Platform Version (Minor)    
◆ bits  7-0  = Platform Type ID [0x1] //0x1 -> CDP    0x8 -> MTP




subtype_id:
◆ bits 31-13 = Reserved Bits
◆ bits 12-11 = Panel Detection. 
00 - limit to HD, 01 - limit to 720p
10 - limit to qHD
11 - limit to FWVGA 
◆ bits 10-8  = DDR Size. default value as 0x0 
◆ bits 7-0   = Platform Subtype


寻找单板的DT文件:
1、 LK中首先会将XBL中初始化获取到的当前主板的chipset id、platform id、pmic等进行整理
2、在LK中有相应的函数来翻译每个DTB信息,如8996平台:
platform_id(chipset)=246  variant_id(platform)=1
subtype=0                 soc_rev=0x30001
pmic0=0x20009             pmic1=2000a


3、然后与DTB信息中的 上述参数进行对比,寻找最合适的DTS配置;


4、获取到最匹配的DTS后,LK会输出一下log:
[5880]Best match DTB tags 246/00000001/00000000/30001/20009/2000a/0/0
msm8996.dtsi. 基础的DTS文件,芯片的基础外设都在其中定义
msm8996-v3.dtsi. 对msm8996.dtsi的扩展,Version3版本
msm8996-coresight-v3.dtsi. V3版本的SOC信息


5、最后需要将设备树在内存中的地址传递给内核


如何配置CDP/MTP


高通建议修改方式是通过修改XML文件然后用脚本生成boot_cdt_array.c以及bin文件,
bin文件可以直接烧录到cdt分区中。


XML文件路径:boot_images/QcomPkg/Tools/cdp_1.0_jedec_lpddr4.xml
用高通脚本生成.c文件以及.bin文件:cdt_generator.py


注意若修改.c文件编译XBL烧录后发现修改不成功,则可能是cdt分区已经烧录了.bin文件,
需要用fastboot擦除cdt分区后,再次开机确认。


XBL中CDT参数输出log,根据此处信息确定platform id以及subtype。


DT使用
利用DT,添加单板驱动:
1、从芯片总的DTSI文件中添加设备节点信息
sound-9335{
    compatible = "qcom,msm8996-asoc-snd-tasha";
    qcom,model = "msm8996-tasha-snd-card";


}
2、在\drive\XXX中加入驱动信息


3、内核启动后就进行调试注册的XXX_probe函数


4、XXX_probe函数中就可以调用linux中OF的API接口获取文件节点信息。
常用的接口:
若from=NULL,则在全局链表of_allnodes中根据name查找合适的device_node。
struct device_node *of_find_node_by_name(struct device_node *from, const char *name)
例如:
struct device_node *np;
np = of_find_node_by_name(NULL,"firmware");


根据设备类型在全局链表of_allnodes中查找匹配的device_node.
struct device_node *of_find_node_by_type(struct device_node *from, const char *type)
例如:
struct device_node *tsi_pci;
tsi_pci=of_find_node_by_type(NULL,"pci");


从设备树中提取gpio口,成功:得到GPIO口编号;失败:负数,绝对值是错误码。
static inline int of_get_named_gpio(struct device_node *np, const char *propname, int index);


驱动编译到内核
1、驱动代码的位置。 drivers/char/xxx.c
2、修改Kconfig文件
3、修改Makefile.
4、修改上一级Makefile和Kconfig.
5、使用make menuconfig,或修改board config文件,编译新内核。


模块制作及调试
模块制作
把xxx.c文件放入drivers/char子目录下,修改
drivers/char/Makefile
obj-m += xxx.o
然后,
make modules,生成模块都drivers/char/xxx.ko
调试
在根文件系统中建立设备文件:
#mknod/dev/XXX c 232 0
加载模块
# insmod YYY
卸载模块
#rmmod YYY


驱动代码设计


1、定义并注册设备(device)
即实现硬件对应的设备(device)结构体。有两种方式,继承已有的设备,新建一种新的
设备。如采用已有的设备,一般需要定义私有的data结构体。
注册设备,即新的设备,加入到系统的device list中。


2、定义并注册设备驱动
实现设备(device)对应的驱动(driver),并加入系统的driver list中。


3、实现设备驱动的file_operations,如probe、open等函数。


高通845
PMIC:提供时钟  怎么提供给clock?
和时钟树的区别?
外设IO口
电源管理的功能,


LDO 线性降压
开关电源  效率高








































猜你喜欢

转载自blog.csdn.net/baiyibin0530/article/details/79999578