LINUX裝置驅動開發之0418__LINUX
來源:互聯網
上載者:User
目前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 線性降壓
開關電源 效率高