以高通平台為例,會在kernel/arch/arm/mach-msm下的相應的board-***.c檔案裡邊用
dt_machine_start()這個巨集定義一系列的晶元。以高通8916為例:
在kernel/arch/arm/mach-msm/board-8916.c檔案裡定義了
//當然下面使用哪個要看一下。
dt_machine_start(msm8916_dt,
"qualcomm technologies, inc. msm 8916 (flattened device tree)")
.map_io = msm8916_map_io,
.init_machine = msm8916_init,
.dt_compat = msm8916_dt_match,
.reserve = msm8916_dt_reserve,
.smp = &msm8916_smp_ops,
machine_end
//下面還定了很多其他名字的,比如msm8939。但最終會根據dt_compat,也就是msm8916_dt_match的名字找到相應的dts檔案。比如
static
const
char *msm8916_dt_match __initconst = ;
這個會找到dts檔案裡邊的對應名字的compatible。比如:
/ ;....
在.init_machine對應的msm8916_init()函式裡,會查詢到裝置所有的platform裝置進行初始化。
static
void __init msm8916_init(void)
const
struct of_device_id of_default_bus_match_table = ,//搜一下******-bus
#ifdef config_arm_amba
,#endif /* config_arm_amba */
{} /* empty terminated list */
};//搜一下上面的comatible,比如「******-bus」可以在類似msm8916.dtsi檔案裡邊找到
&soc ;
//....
在找到******-bus並初始化&soc下面所有的platform device之後,就可以在
sys/devices/soc.0下面找到所有的device節點。比如拿上面tsens為例會根據device tree設定的名字platform device id等給裝置取名字。
/sys/devices/soc.0/4a8000.tsens
而且platform device建立的時候在platform_device_add函式中,dev.bus都會預設設定成platform_bus_type
所以上面4a8000.tsens也會在/sys/bus/platform/devices下面生成一樣的節點,並被symlink。
/sys/bus/platform/devices # ls -l
lrwxrwxrwx root root 2015-01-13
18:30
4a8000.tsens -> ../../../devices/soc.0/4a8000.tsens
platform裝置的名字,通常是@後面的名字.加上:後面的名字。如果什麼都沒有,就名字加上platform id。
但也有例外,確切的device tree節點名字讀一下uevent節點就可以知道。
cpubw: qcom,cpubw@0 {}就會生成/sys/devices/soc.0/0.qcom,cpubw
qcom,armbw-pm {}就會生成/sys/devices/soc.0/qcom,armbw-pm
.32
當然&soc{}這個有效果的前提也是需要包含在整個device tree的根目錄下。
/ ;
aliases ;
cpus ;
};cpu1: cpu@1 ;
cpu2: cpu@2 ;
cpu3: cpu@3 ;
};soc: soc ;//沒有這個,platform裝置相關的&soc{}包含的都是不會被初始化的!!!
};
具體的platform驅動在找到對應的compatible的名字之後,就可以新增裝置驅動。
這個過程中會在/sys/bus/platform/driver目錄下生成與驅動的名字對應名字的節點。
比如下面定義的platform driver在被找到對應的platform device之後會生成
相應的節點。
static struct platform_driver mdm_driver = ,
};生成的節點是:
/sys/bus/platform/drivers/ext-mdm
現在platform device都是從device tree裡邊讀出並進行platform device的初始化。
以前是對應platform device和platform driver的名字的話,現在是對比device相關的compatible的內容了。
像下面i2c-versatile驅動中,在i2c_versatile_match.compatible的字串,如果與某個&soc{}裡邊的compatible內容一致,就回去呼叫相應的probe函式去初始化platform。
drivers/i2c/busses/i2c-versatile.c檔案裡邊可以看到像下面的基本的platform裝置的定義以及函式呼叫
static
const
struct of_device_id i2c_versatile_match = ,
{},};module_device_table(of, i2c_versatile_match);
static
struct platform_driver i2c_versatile_driver = ,
};static
int __init i2c_versatile_init(void)
static
void __exit i2c_versatile_exit(void)
subsys_initcall(i2c_versatile_init);
module_exit(i2c_versatile_exit);
module_description("arm versatile i2c bus driver");
module_license("gpl");
module_alias("platform:versatile-i2c");
/sys/bus/platform/devices/versatile-i2c.0/
modalias ,uevent這幾個檔案,power,subsystem資料夾
/sys/devices/platform/versatile-i2c.0/
modalias ,uevent這幾個檔案,power,subsystem資料夾
int platform_driver_register(struct platform_driver *drv)
struct bus_type platform_bus_type= ;
static
struct device_attribute platform_dev_attrs = ;
這裡的platform_bus_type會用bus_register()先註冊一下。
int bus_register(struct bus_type *bus)
priv->drivers_kset = kset_create_and_add("drivers", null,
&priv->subsys.kobj);
if (!priv->drivers_kset)
init_list_head(&priv->inte***ces);
__mutex_init(&priv->mutex, "subsys mutex", key);
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, null, null);
retval = add_probe_files(bus);
if (retval)
goto bus_probe_files_fail;
retval = bus_add_attrs(bus);
if (retval)
goto bus_attrs_fail;
pr_debug("bus: '%s': registered\n", bus->name);
return
0;bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
out:
kfree(bus->p);
bus->p =
null;
return retval;
}
待續…. Linux驅動基礎
裝置驅動充當了硬體和應用軟體之間的紐帶,它使得應用軟體只需要呼叫系統軟體的應用程式設計介面 api 就可讓硬體去完成要求的工作。本文主要講解了linux裝置驅動與硬體的關係,linux裝置驅動的開發模式以及核心中相關的重要基礎資料結構。對裝置驅動最通俗的解釋就是 驅使硬體裝置行動 驅動與底層硬體直接...
Linux驅動模組基礎
1 模組載入函式 linux核心模組載入函式一般以 init標識宣告,典型的模組載入函式的形式如下 static int init initialization function void module init initialization function 模組載入函式必須以 module in...
Linux驅動基礎開發1
目前,linux軟體工程師大致可分為兩個層次 主要利用c庫函式和linux api進行應用軟體的編寫 從事這方面的開發工作,主要需要學習 符合linux posix標準的api函式及系統呼叫,linux的多工程式設計技巧 多程序 多執行緒 程序間通訊 多工之間的同步互斥等,嵌入式資料庫的學習,ui程...