現象:驅動模組載入時呼叫 `clk_get(NULL, "adc")` → `clk_enable()` → `clk_get_rate()` → `printk`,但 `dmesg` 無輸出。
排查清單
- 時鐘名稱是否匹配 Device Tree:
`clk_get(NULL, "adc")` 中的 `"adc"` 必須與 DTS 中 `clock-names = "adc";` 完全一致(區分大小寫)。
- 驅動 probe 順序:
確保 ADC 控制器驅動已註冊時鐘提供者(`of_clk_add_provider`),否則 `clk_get` 返回 `-ENOENT`。
- `printk` 級別與緩衝:
預設 `printk` 級別可能被過濾,改用 `pr_info()` 或 `dev_info(&pdev->dev, ...)`;或檢查 `dmesg -n 8` 提高輸出級別。
- 模組載入時機:
若在 `module_init` 中執行,時鐘子系統可能未就緒,改為 `late_initcall` 或在 `probe` 中延遲執行。
- 編譯條件:
確認 `CONFIG_COMMON_CLK`、`CONFIG_CLKDEV_LOOKUP` 已啟用(`make menuconfig` → Device Drivers → Common Clock Framework)。
驗證步驟
# 1. 查看時鐘樹確認名稱
cat /sys/kernel/debug/clk/clk_summary | grep -i adc
# 2. 載入模組後查看完整 dmesg
dmesg -T | tail -30
# 3. 若 clk_get 失敗,檢查返回值
struct clk *clk = clk_get(NULL, "adc");
if (IS_ERR(clk)) {
pr_err("clk_get failed: %ld\n", PTR_ERR(clk));
return PTR_ERR(clk);
}
常見解決方案
- DTS 中補全 `clock-names` 與 `clocks` phandle。
- 驅動改用 `devm_clk_get(&pdev->dev, "adc")` 自動管理生命週期。
- 在 `probe` 末尾或 `platform_driver` 的 `probe` 後註冊 `late_initcall` 獲取頻率。
核心原則:先確認 DTS 時鐘描述正確,再驗證驅動 probe 時機,最後用 `pr_err` 打印錯誤碼定位。