學習了linux的dts和platform總線機制,自己畫圖概括了一下dts文件,設備,總線和驅動之間的相互關係.
爲了證實一下,在NanoPi-NEO上進行了如下試驗, NanoPi-NEO上已經預裝了Ubuntu-Core Linux_4.11 固件:
1. 將friendlyarm官方源碼linux_4.11.2_20170531.tar.gz 解壓到NanoPi-NEO的 /works 目錄下,並按照說明完成編譯。
2. 在 /works/linux/arch/arm/boot/dts 目錄下建立一個midas.dtsi文件,添加一個midas節點,內容如下:
/{
midas {
compatible = "midas,dts_test";
reg=<0x12344321 0x1>;
midas_value=<555>;
label = "Midas_Label";
};
};
然後將它引用到 sun8i-h3-nanopi-neo.dts 文件中 #include "midas.dtsi"
3. 在/works/linux 目錄下執行 make dtbs 命令,成功後會生成dtb文件 /works/linux/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dtb,將它複製到/boot下覆蓋原來的同名文件, 然後重啓linux,內核加載新的dtb.
4. 編輯一個platf_test.c文件, 內容如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_platform.h>
static struct of_device_id my_match_table[] = {
{ .compatible = "midas,dts_test", },
{ },
};
static int my_probe(struct platform_device *dev)
{
struct resource *res_mem;
struct device_node *node_midas;
int value;
char *label;
if( dev && (dev->name))
{
printk("--- dts_test: a compatibale device is found! -----");
printk("matched platform_device: name=%s id=%d num_resources=%d\n",dev->name,dev->id,dev->num_resources);
res_mem = platform_get_resource(dev,IORESOURCE_MEM,0);
printk("get MEM resource: name=%s, start=0x%08x, end=0x%08x\n",res_mem->name,res_mem->start,res_mem->end);
//----- get node -----
node_midas = dev->dev.of_node;
//----- get u32 value of a property -----
if(!of_property_read_u32(node_midas,"midas_value",&value))
printk("value: %d ",value);
else
printk("no property with name 'midas_value' \n");
//----- get property of a label string -----
label=(char *)of_get_property(node_midas,"label",NULL); /* return void */
if(label)
printk("label: %s \n",label);
else
printk("no property with name 'label' \n");
}
else
printk("name unknwon \n");
return 0;
}
static struct platform_driver my_driver = {
.probe = my_probe,
.driver = {
.owner = THIS_MODULE,
.name = "midas",
.of_match_table = my_match_table, //platform_bus will try to match .of_match_table first, and then .name
},
};
static int __init platf_test_init(void)
{
printk("------ dts v.s. platform driver start -----\n");
return platform_driver_register(&my_driver);
}
static void __exit platf_test_exit(void)
{
platform_driver_unregister(&my_driver);
printk("------ dts v.s. platform driver exit -----\n");
}
module_init(platf_test_init);
module_exit(platf_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Midas");
MODULE_DESCRIPTION("platf_test");
並編輯一個對應的Makefile如下:
obj-m := platf_test.o
PWD := $(shell pwd)
K_DIR := /works/linux
all:
$(MAKE) -C $(K_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(K_DIR) M=$(PWD) clean
5. make 一下, 在當前目錄下會生成 platf_test.ko
6. insmod platf_test.ko 加載內核模塊,觀察運行結果:
注意到 /sys/bus/platform/devices下生成的設備名:
(水平所限,如有錯誤還請斧正.)