解決一個驅動代碼解耦合問題
之前解決的項目LCD設備兼容問題,在 a.c 文件里面定義了一個變量,然后在 b.c 里面使用 extern聲明引用這個變量,通過這種方法可以在b.c中使用在a.c 里面初始化的變量。

但是這中情況就會引起一個問題,就是驅動代碼之間耦合了,這也違背了驅動代碼 高內聚、低耦合的思想。
所以,這篇文章就是討論解決這個問題的。
之前寫的文章
1、先說說問題產生的本質
在 a.c 驅動文件中,我會根據 dts 文件的配置掛載一個platform 驅動,這個驅動獲取dts文件的 gpio口信息,申請gpio口,并賦值給 g_lcm_power變量。
代碼如下
dts文件
?panel:?panel@0?{
??compatible?=?"hx8279d";
??gpio_lcd_pwr_en?=?<&pio?47?0>;
??status?=?"okay";
?};
驅動文件
static?const?struct?of_device_id?lcm_platform_of_match[]?=?{
?{
??.compatible?=?"hx8279d",
??.data?=?0,
??},?{
??????/*?sentinel?*/
??????}
};
MODULE_DEVICE_TABLE(of,?platform_of_match);
static?int?lcm_platform_probe(struct?platform_device?*pdev)
{
?const?struct?of_device_id?*id;
?enum?of_gpio_flags?flags;
?int?ret;
?struct?device_node?*node?=?pdev->dev.of_node;
?PRINTFx("[Kernel/LCM]?lcm_platform_probe()?enter\n");
?id?=?of_match_node(lcm_platform_of_match,?pdev->dev.of_node);
?if?(!id)
??return?-ENODEV;
?g_lcm_power?=?of_get_named_gpio_flags(node,?"gpio_lcd_pwr_en",?0,?&flags);
?if?(!gpio_is_valid(g_lcm_power))?{
??dev_err(&pdev->dev,?"invalid?en?gpio%d\n",?g_lcm_power);
?}
?ret?=?devm_gpio_request(&pdev->dev,?g_lcm_power,?"gpio_lcd_pwr_en");
?if?(ret)?{
??dev_err(&pdev->dev,
????"failed?to?request?GPIO%d?for?relay-en-gpio\n",
????g_lcm_power);
??return?-EINVAL;
?}
?return?0;
}
static?struct?platform_driver?lcm_driver?=?{
?.probe?=?lcm_platform_probe,
?.driver?=?{
?????.name?=?"hx8279d",
?????.owner?=?THIS_MODULE,
?????.of_match_table?=?lcm_platform_of_match,
?????},
};
static?int?__init?lcm_init(void)
{
?PRINTFx("[Kernel/LCM]?lcm_init()?probe?enter\n");
????/*
?if?(platform_driver_register(&lcm_driver))?{
??PRINTFx("LCM:?failed?to?register?this?driver!\n");
??return?-ENODEV;
?}
????*/
?return?0;
}
static?void?__exit?lcm_exit(void)
{
?platform_driver_unregister(&lcm_driver);
}
late_initcall(lcm_init);
module_exit(lcm_exit);
MODULE_AUTHOR("mediatek");
MODULE_DESCRIPTION("LCM?display?subsystem?driver");
MODULE_LICENSE("GPL");
a.c 文件 和 b.c 文件的只能執(zhí)行一個lcm 驅動,具體執(zhí)行哪個驅動是在lk判斷硬件接了哪一個硬件模組,所以我們在實現驅動代碼的時候,a.c驅動文件和b.c驅動文件都需要具備注冊上述說的那個 power gpio代碼,用來控制模組的電源。
我的解決辦法是
在 a.c 驅動文件中,我會根據 dts 文件的配置掛載一個platform 驅動,這個驅動獲取dts文件的 gpio口信息,申請gpio口,并賦值給 g_lcm_power變量。
因為a.c的platform驅動我是默認每次開機都會加載。
在b.c驅動文件中,我使用 extern int g_lcm_power;來聲明這個變量,這樣做之后,如果在lk識別到b.c的驅動,這個變量也可以正常使用。
2、什么是高內聚、低耦合?
這是之前寫的一篇文章,我覺得解釋的比較不錯了。
3、如何解決這樣的問題?
如何解決,也就是說我們要對驅動代碼進行解耦合。
因為我們代碼中就只對一個對GPIO口的控制,如果脫離DTS的注冊,直接在驅動文件里面對這個GPIO口進行操作的話,理論上就可以解決耦合的問題了。
這部分可以去查一下下面這個函數
gpio_direction_output
測試看看如果在不申請的情況下是否可以使用。
第二種情況就還是使用dts來匹配
dts改成如下
?panel:?panel@0?{
??/*compatible?=?"hx8279d";*/
??gpio_lcd_pwr_en?=?<&pio?47?0>;
??status?=?"okay";
?};
在 a.c 和 b.c 驅動中,同時使用如下代碼申請gpio口,linux的dts是一個很不錯組織結構,也有很多函數來獲取dts中的文件。
想研究dts的同學,可以看看這個目錄下的內容,對大家調試非常有幫助。

static?void?lcm_init_power(void)
{
?struct?device_node?*panel_nd;
?int?ret;
?enum?of_gpio_flags?flags;
?PRINTFx("[Kernel/LCM]?lcm_init_power()?enter\n");
????/*查找整個dts文件,找到panel,前面是NULL就是讓這個函數查找整個dts*/
?panel_nd?=?of_find_node_by_name(NULL,?"panel");
?if(!panel_nd){
??PRINTFx("Can't?file?panel_nd?node\n");
??return;
?}
????/*獲取gpio_lcd_pwr_en屬性信息*/
?g_lcm_power?=?of_get_named_gpio_flags(panel_nd,?"gpio_lcd_pwr_en",?0,?&flags);
?PRINTFx("1212121g_lcm_power=%d\n",?g_lcm_power);
?if?(!gpio_is_valid(g_lcm_power))?{
??PRINTFx("invalid?en?gpio%d\n",?g_lcm_power);
??return;
?}
?ret?=?gpio_request(?g_lcm_power,?"gpio_lcd_pwr_en");
?if?(ret)?{
??PRINTFx("failed?to?request?GPIO%d?for?relay-en-gpio\n",g_lcm_power);
??return;
?}
?PRINTFx("[Kernel/LCM]?lcm_init_power()?end\n");
?return;
#ifndef?BUILD_LK
?PRINTFx("[Kernel/LCM]?lcm_init()?enter\n");
#endif
}


