Linux kernel 使用 regulator 框架來管理電源,比如 PMIC 芯片上常見的LDO。使用 regulator 的常規流程如以下代碼所示:
void set_vbus_voltage(struct device *dev) { struct regulator *vbus; vbus = regulator_get(dev, "vbus"); if (IS_ERR(vbus)) { ret = PTR_ERR(vbus); goto reg_put; } regulator_set_voltage(vbus, 5000000, 5000000); regulator_enable(vbus); reg_put: regulator_put(vbus); }
IS_ERR宏用來判斷 regulator_get 的返回值是否有錯誤,如果沒有錯誤,表示成功 get 到這個 regulator,那么就可以進行后續的 set 和 enable 操作了。這個設計符合我們的思維習慣。
那么對於上例,當 IS_ERR(vbus) 返回假時,也就是成功 get 到了名為 vbus 的 regulator,是否代表 vbus 這個 regulator 一定會起作用,輸出 5V 呢?答案是不一定。
假設我們並沒有在設備樹中定義或者代碼中創建“vbus”這個 regulator,比如我們一不小心搞錯了regulator的名字,這個 regulator 的正確名字應該是 “vusbhost”,而不是 “vbus”,那么IS_ERR宏能判定出來嗎?按我們的思維習慣應該是會返回真,也就是判定 get regulator 出錯了;但是實際情況恰恰相反,IS_ERR宏仍然返回假,也就是判定 get regulator 成功。為什么會發生這種情況呢,這就需要看一下 regulator_get 函數的具體實現。
如上圖,regulator_get 最終會調用到 _regulator_get。結合紅色箭頭1和2所指向的代碼,可以看出代碼邏輯是:如果找不到對應名字的 regulator,那么就返回 dummy regulator,並且在 kernel log 中輸出相關 warning 信息。比如上例中如果找不到 “vbus”,則會輸出如下 warning:
supply vbus not found, using dummy regulator
同時作者還在注釋中給出了理由:“假設某個 regulator 是物理硬件上存在並已經使能了的,如果軟件中找不到,那么就提供一個 dummy regulator 設備”。
所以當我們在調試驅動時,如果發現某個 regulator 沒有按預期輸出,且跟蹤代碼流程也沒有發現中途出錯返回,那么不妨考慮一下上述情況,仔細看看 kernel log 中有沒有相關的 warning。
作者:bigfish99
博客:https://www.cnblogs.com/bigfish0506/
公眾號:大魚嵌入式